diff --git a/include/dataAcquisition.h b/include/dataAcquisition.h index 5443f42..ea9f025 100644 --- a/include/dataAcquisition.h +++ b/include/dataAcquisition.h @@ -12,7 +12,7 @@ int getSensorsNumber(); int getSlidingWindowSize(); bool isFull(int sensorIndex); -void addReading(float value, int sensorIndex); +void addReading(float value); float getAverageOnSensor(int sensorIndex); float getAverageOnAllSensors(); diff --git a/libraries/dataAcquisition.c b/libraries/dataAcquisition.c index 4e9c78f..a5cff49 100644 --- a/libraries/dataAcquisition.c +++ b/libraries/dataAcquisition.c @@ -11,20 +11,56 @@ static int sensorsNumber; static int slidingWindowSize; +/** + * @brief Sets the number of sensors. + * + * This function sets the global variable `sensorsNumber` to the specified value. + * + * @param number The number of sensors to set. + */ static void setSensorsNumber(int number) { sensorsNumber = number; } +/** + * @brief Sets the size of the sliding window. + * + * This function sets the size of the sliding window used for data acquisition. + * + * @param size The desired size of the sliding window. + */ static void setSlidingWindowSize(int size) { slidingWindowSize = size; } +/** + * @brief Initializes the sensor readings array. + * + * This function allocates memory for a 2D array to store sensor readings. + * Each sensor will have a sliding window of readings. + * + * @param numSensors The number of sensors. + * @param windowSize The size of the sliding window for each sensor. + * + * The function performs the following steps: + * 1. Allocates memory for the array of sensor readings. + * 2. Allocates memory for each sensor's sliding window of readings. + * 3. Sets the number of sensors and the sliding window size using private setter functions. + * + * If memory allocation fails at any point, the function prints an error message and exits the program. + */ void initializeReadings(int numSensors, int windowSize) { + + // Allocate memory for the array of sensor readings readings = (float **)malloc(numSensors * sizeof(float *)); + + // Check if memory allocation was successful if (readings == NULL) { perror("Failed to allocate memory for readings"); exit(EXIT_FAILURE); } + + // Allocate memory for each sensor's sliding window of readings for (int i = 0; i < numSensors; i++) { readings[i] = (float *)calloc(windowSize, sizeof(float)); if (readings[i] == NULL) { @@ -32,11 +68,21 @@ void initializeReadings(int numSensors, int windowSize) { exit(EXIT_FAILURE); } } - // Chiamate private ai setter + + // Calling the private setter functions setSensorsNumber(numSensors); setSlidingWindowSize(windowSize); } +/** + * @brief Frees the memory allocated for sensor readings. + * + * This function iterates through the array of sensor readings and frees the memory + * allocated for each individual reading. After freeing all individual readings, it + * checks if the main readings array is not NULL and frees it as well. + * + * @return true if the main readings array was successfully freed, false otherwise. + */ bool freeReadings() { for (int i = 0; i < sensorsNumber; i++) { free(readings[i]); @@ -44,26 +90,49 @@ bool freeReadings() { if(readings != NULL){ free(readings); + readings = NULL; return true; } else{ return false; } - } -// Functions - +/** + * @brief Get the number of sensors. + * + * This function returns the total number of sensors currently available. + * + * @return int The number of sensors. + */ // Get the number of sensors int getSensorsNumber() { return sensorsNumber; } +/** + * @brief Get the sliding window size. + * + * This function returns the current size of the sliding window used in data acquisition. + * + * @return The size of the sliding window. + */ // Get the sliding window size int getSlidingWindowSize() { return slidingWindowSize; } +/** + * @brief Checks if the sliding window for a given sensor is full. + * + * This function iterates through the readings of a specified sensor and + * determines if all entries in the sliding window are non-zero, indicating + * that the window is full. + * + * @param sensorIndex The index of the sensor to check. + * @return true if the sliding window is full (all entries are non-zero), + * false otherwise. + */ // Control on the fullness of the sliding window bool isFull(int sensorIndex) { for (int i = 0; i < slidingWindowSize; i++) { @@ -74,6 +143,16 @@ bool isFull(int sensorIndex) { return true; } +/** + * @brief Retrieves the last reading from the specified sensor. + * + * This function returns the most recent reading from the sensor identified by + * the given index. If the sensor's data buffer is full, it returns the last + * value in the buffer. Otherwise, it returns the first value. + * + * @param sensorIndex The index of the sensor to retrieve the reading from. + * @return The last reading from the specified sensor. + */ float getLastReading(int sensorIndex) { if (isFull(sensorIndex)) { return readings[sensorIndex][slidingWindowSize - 1]; @@ -82,8 +161,21 @@ float getLastReading(int sensorIndex) { } } -// Add a reading to the readings array -void addReading(float value, int sensorIndex) { +static int lastSensorIndex = -1; + +/** + * @brief Adds a new sensor reading to the data acquisition system. + * + * This function updates the readings for the sensors in a circular buffer manner. + * If the buffer for a sensor is full, it shifts the readings to make space for the new value. + * If the buffer is not full, it adds the new value to the first available position. + * + * @param value The new sensor reading to be added. + */ +void addReading(float value) { + lastSensorIndex = (lastSensorIndex + 1) % sensorsNumber; + int sensorIndex = lastSensorIndex; + if (isFull(sensorIndex)) { for (int i = 0; i < slidingWindowSize - 1; i++) { readings[sensorIndex][i] = readings[sensorIndex][i + 1]; @@ -93,15 +185,22 @@ void addReading(float value, int sensorIndex) { for (int i = 0; i < slidingWindowSize; i++) { if (readings[sensorIndex][i] == 0) { readings[sensorIndex][i] = value; - // Update the position index - break; } - } } } +/** + * @brief Calculates the average reading for a specified sensor. + * + * This function computes the average of the readings stored in a sliding window + * for the sensor specified by the sensorIndex parameter. If the sliding window + * is not full, the function prints a message and returns 0. + * + * @param sensorIndex The index of the sensor for which the average reading is to be calculated. + * @return The average reading of the specified sensor if the sliding window is full; otherwise, returns 0. + */ float getAverageOnSensor(int sensorIndex) { if(isFull(sensorIndex) == false){ printf("The sliding window is not full\n"); @@ -116,6 +215,14 @@ float getAverageOnSensor(int sensorIndex) { } } +/** + * @brief Calculates the average reading from all sensors. + * + * This function iterates through all available sensors, retrieves the last reading + * from each sensor, and calculates the average of these readings. + * + * @return The average reading from all sensors as a float. + */ float getAverageOnAllSensors() { float sum = 0; for (int i = 0; i < sensorsNumber; i++) { @@ -124,6 +231,18 @@ float getAverageOnAllSensors() { return sum / sensorsNumber; } +/** + * @brief Calculates the overall average of sensor readings. + * + * This function iterates through all sensors and their respective sliding windows + * to calculate the overall average of the readings. It first checks if the sliding + * window for each sensor is full. If any sliding window is not full, it prints a + * message indicating which sensor's sliding window is not full and returns 0. + * Otherwise, it sums up all the readings from all sensors and calculates the average. + * + * @return The overall average of the sensor readings if all sliding windows are full, + * otherwise returns 0. + */ float getOverallAverage() { float sum = 0; int totalReadings = 0; @@ -140,6 +259,18 @@ float getOverallAverage() { return sum / totalReadings; } +/** + * @brief Calculates the standard deviation of sensor readings. + * + * This function computes the standard deviation of the readings from a specified sensor. + * It first checks if the sliding window for the sensor is full. If not, it prints a message + * and returns 0. If the sliding window is full, it calculates the average of the readings, + * then computes the sum of the squared differences between each reading and the average. + * Finally, it returns the square root of the average of these squared differences. + * + * @param sensorIndex The index of the sensor for which the standard deviation is to be calculated. + * @return The standard deviation of the sensor readings, or 0 if the sliding window is not full. + */ float getStandardDeviationOnSensor(int sensorIndex) { if(isFull(sensorIndex) == false){ printf("The sliding window is not full\n"); @@ -155,6 +286,16 @@ float getStandardDeviationOnSensor(int sensorIndex) { } } +/** + * @brief Calculates the standard deviation of the readings from all sensors. + * + * This function computes the standard deviation of the sensor readings by first + * calculating the average of all sensor readings, then summing the squared + * differences between each reading and the average, and finally taking the + * square root of the average of these squared differences. + * + * @return The standard deviation of the sensor readings. + */ float getStandardDeviationOnAllSensors() { float sum = 0; float average = getAverageOnAllSensors(); @@ -166,12 +307,27 @@ float getStandardDeviationOnAllSensors() { return sqrt(sum / sensorsNumber); } +/** + * @brief Detects anomalies in sensor readings based on a given average and standard deviation. + * + * This function calculates the upper and lower thresholds for anomaly detection using a 97% confidence interval. + * It then iterates through the sensor readings within a sliding window and counts the number of outliers that fall + * outside the calculated thresholds. + * + * @param average The average value of the sensor readings. + * @param standardDeviation The standard deviation of the sensor readings. + * + * @note The function uses a confidence interval multiplier of 2.17 to determine the thresholds. + * @note The variable `outlierCount` is used to store the number of detected outliers. + * @note The variables `slidingWindowSize` and `sensorsNumber` are assumed to be defined globally. + * @note The 2D array `readings` is assumed to contain the sensor data. + */ void anomalyDetect(float average, float standardDeviation) { float upperThreshold = average + 2.17 * standardDeviation; // 97% confidence interval float lowerThreshold = average - 2.17 * standardDeviation; // Lower bound for anomaly detection outlierCount = 0; - for (int i = 0; i < sensorsNumber; i++) { - for (int j = 0; j < slidingWindowSize; j++) { + for (int j = 0; j < slidingWindowSize; j++) { + for (int i = 0; i < sensorsNumber; i++) { if (readings[i][j] > upperThreshold || readings[i][j] < lowerThreshold) { outlierCount++; } @@ -180,6 +336,17 @@ void anomalyDetect(float average, float standardDeviation) { } +/** + * @brief Calculates the overall standard deviation of sensor readings. + * + * This function computes the overall standard deviation of the readings from multiple sensors. + * It first checks if the sliding window for each sensor is full. If any sensor's sliding window + * is not full, it prints a message and returns 0. Otherwise, it calculates the sum of the squared + * differences between each reading and the overall average, and then computes the standard deviation. + * The function also calls `anomalyDetect` with the calculated average and standard deviation. + * + * @return The overall standard deviation of the sensor readings. Returns 0 if any sensor's sliding window is not full. + */ float getOverallStandardDeviation() { float sum = 0; int totalReadings = 0; @@ -202,6 +369,14 @@ float getOverallStandardDeviation() { return totalStandardDeviation; } +/** + * @brief Retrieves the current count of outliers. + * + * This function returns the number of outliers detected and stored in the + * variable `outlierCount`. + * + * @return The number of outliers. + */ int getOutlierCount() { return outlierCount; } \ No newline at end of file diff --git a/test/test_dataAcquisition.c b/test/test_dataAcquisition.c index b790703..465dc7b 100644 --- a/test/test_dataAcquisition.c +++ b/test/test_dataAcquisition.c @@ -17,7 +17,18 @@ #define NORMAL_DISTRIBUTION_MEAN 10.0 #define NORMAL_DISTRIBUTION_STDDEV 2.0 -// Testing the initialization and the instantiation of the sensors' number and sliding window size for uniform distribution + +/** + * @brief Test function to verify the initialization of sensor readings. + * + * This function tests the `initializeReadings` function by initializing the + * readings with a specified number of sensors and sliding window size. It then + * asserts that the number of sensors and the sliding window size are correctly + * set. + * + * @note This test assumes that the constants `NUMBER_OF_SENSORS` and + * `SLIDING_WINDOW_SIZE` are defined elsewhere in the code. + */ void test_initializeReadings_uniform() { initializeReadings(NUMBER_OF_SENSORS, SLIDING_WINDOW_SIZE); @@ -25,20 +36,35 @@ void test_initializeReadings_uniform() assert(getSlidingWindowSize() == SLIDING_WINDOW_SIZE); } -// Testing the logic of add readings to see if the sliding window is full for uniform distribution +/** + * @brief Test function to add uniform readings to all sensors and verify if the last sensor's buffer is full. + * + * This function iterates through a range of values from 1 to SLIDING_WINDOW_SIZE and adds each value to all sensors. + * After adding the readings, it asserts that the buffer for the last sensor (NUMBER_OF_SENSORS - 1) is full. + * + * @note Assumes that the addReading function adds a reading to all sensors and that the isFull function checks if a sensor's buffer is full. + */ void test_addReading_uniform() { - for (int sensor = 0; sensor < NUMBER_OF_SENSORS; sensor++) + for (int value = 1; value <= SLIDING_WINDOW_SIZE; value++) { - for (int value = 1; value <= SLIDING_WINDOW_SIZE; value++) + for (int sensor = 0; sensor < NUMBER_OF_SENSORS; sensor++) { - addReading(value, sensor); + addReading(value); } } assert(isFull(NUMBER_OF_SENSORS - 1) == true); // Assuming the last sensor acquired the data } -// Testing the logic of average methods for uniform distribution +/** + * @brief Test function to verify the average calculation on a sensor with uniform data. + * + * This function tests the `getAverageOnSensor` function by calculating the average + * value on the last sensor (NUMBER_OF_SENSORS - 1) and comparing it to the expected + * average value. The expected average is calculated as (SLIDING_WINDOW_SIZE + 1) / 2.0. + * The test asserts that the difference between the calculated average and the expected + * average is within the defined AVERAGE_UNCERTAINTY. + */ void test_averageOnSensor_uniform() { //printf("Average on sensor %d: %f\n", NUMBER_OF_SENSORS - 1, getAverageOnSensor(NUMBER_OF_SENSORS - 1)); @@ -47,6 +73,21 @@ void test_averageOnSensor_uniform() assert(fabs(average - expected_average) < AVERAGE_UNCERTAINTY); } +/** + * @brief Test the standard deviation calculation on the last sensor with uniform data. + * + * This function tests the standard deviation calculation for the last sensor + * in the array of sensors. It compares the calculated standard deviation with + * an expected value to ensure the accuracy of the standard deviation function. + * + * The test uses the following steps: + * 1. Calculate the standard deviation for the last sensor. + * 2. Define the expected standard deviation value. + * 3. Assert that the difference between the calculated and expected values is + * within an acceptable uncertainty range (STD_UNCERTAINTY). + * + * @note The expected standard deviation value is hardcoded as 2.872281323269. + */ void test_standardDeviationOnSensor_uniform() { //printf("Standard deviation on sensor %d: %f\n", NUMBER_OF_SENSORS - 1, getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1)); @@ -55,6 +96,14 @@ void test_standardDeviationOnSensor_uniform() assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); } +/** + * @brief Test function to verify the average calculation on all sensors when the values are uniform. + * + * This function calculates the average value from all sensors using the `getAverageOnAllSensors` function + * and compares it to the expected average value, which is defined by `SLIDING_WINDOW_SIZE`. + * The test asserts that the difference between the calculated average and the expected average + * is within the acceptable uncertainty range defined by `AVERAGE_UNCERTAINTY`. + */ void test_averageOnAllSensors_uniform() { //printf("Average on all sensors: %f\n", getAverageOnAllSensors()); @@ -63,6 +112,19 @@ void test_averageOnAllSensors_uniform() assert(fabs(average - expected_average) < AVERAGE_UNCERTAINTY); } +/** + * @brief Test the standard deviation calculation on all sensors with uniform data. + * + * This function tests the `getStandardDeviationOnAllSensors` function by comparing + * the calculated standard deviation with the expected value of 0. The test assumes + * that all sensors have uniform data, resulting in a standard deviation of 0. + * + * The test passes if the absolute difference between the calculated standard deviation + * and the expected standard deviation is less than the defined uncertainty (`STD_UNCERTAINTY`). + * + * @note The `printf` statement is commented out and can be used for debugging purposes + * to print the calculated standard deviation. + */ void test_standardDeviationOnAllSensors_uniform() { //printf("Standard deviation on all sensors: %f\n", getStandardDeviationOnAllSensors()); @@ -71,6 +133,16 @@ void test_standardDeviationOnAllSensors_uniform() assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); } +/** + * @brief Test the overall average calculation with uniform sensor data. + * + * This function tests the `getOverallAverage` function by comparing the + * calculated average with the expected average value when all sensors + * have uniform data. The expected overall average is calculated as + * (SLIDING_WINDOW_SIZE + 1) / 2.0. The test asserts that the difference + * between the calculated average and the expected average is within + * the defined uncertainty (AVERAGE_UNCERTAINTY). + */ void test_overallAverage_uniform() { //printf("Overall average on all sensors: %f\n", getOverallAverage()); @@ -79,6 +151,17 @@ void test_overallAverage_uniform() assert(fabs(average - expected_overall_average) < AVERAGE_UNCERTAINTY); } +/** + * @brief Test the overall standard deviation for uniform distribution. + * + * This function tests the standard deviation calculation for the last sensor + * in a uniform distribution scenario. It compares the calculated standard + * deviation with the expected value and asserts that the difference is within + * an acceptable uncertainty range. + * + * @note The expected standard deviation value is hardcoded as 2.872281323269. + * The acceptable uncertainty range is defined by the macro STD_UNCERTAINTY. + */ void test_overallStandardDeviation_uniform() { //printf("Overall standard deviation: %f\n", getOverallStandardDeviation()); @@ -87,6 +170,27 @@ void test_overallStandardDeviation_uniform() assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); } +/** + * @brief Test function for anomaly detection with uniform data. + * + * This function tests the anomaly detection mechanism by: + * 1. Calculating the overall average and standard deviation of the data. + * 2. Detecting anomalies based on the calculated average and standard deviation. + * 3. Asserting that the initial outlier count is zero. + * 4. Adding an outlier to the data. + * 5. Recalculating the overall average and standard deviation. + * 6. Detecting anomalies again with the updated data. + * 7. Asserting that the outlier count is one after adding the outlier. + * + * The function uses the following helper functions: + * - getOverallAverage(): Returns the overall average of the data. + * - getOverallStandardDeviation(): Returns the overall standard deviation of the data. + * - anomalyDetect(float average, float standard_deviation): Detects anomalies based on the provided average and standard deviation. + * - getOutlierCount(): Returns the current count of outliers detected. + * - addReading(float value): Adds a new reading to the data set. + * + * The assertions use a tolerance of 0.01 to account for floating-point precision errors. + */ void test_anomalyDetect_uniform() { float average = getOverallAverage(); @@ -96,7 +200,7 @@ void test_anomalyDetect_uniform() assert(fabs(getOutlierCount() - 0) < 0.01); // Adding an outlier - addReading(20, NUMBER_OF_SENSORS - 1); + addReading(20); average = getOverallAverage(); standard_deviation = getOverallStandardDeviation(); anomalyDetect(average, standard_deviation); @@ -104,6 +208,14 @@ void test_anomalyDetect_uniform() assert(fabs(getOutlierCount() - 1) < 0.01); } +/** + * @brief Unit test for the freeReadings function. + * + * This function tests the freeReadings function to ensure it correctly + * frees the allocated memory and returns true upon successful execution. + * + * @note This test uses the assert function to verify the expected behavior. + */ void test_freeReadings() { assert(freeReadings() == true); @@ -113,6 +225,16 @@ void test_freeReadings() // TODO: Evaluate the normal distribution with the anomaly detection +/** + * @brief Test the initialization of sensor readings with normal parameters. + * + * This function tests the `initializeReadings` function by initializing the readings + * with a specified number of sensors and sliding window size. It then asserts that + * the number of sensors and the sliding window size are correctly set. + * + * @note This test assumes that the constants `NUMBER_OF_SENSORS` and `SLIDING_WINDOW_SIZE` + * are defined elsewhere in the code. + */ void test_initializeReadings_normal() { initializeReadings(NUMBER_OF_SENSORS, SLIDING_WINDOW_SIZE); @@ -120,23 +242,48 @@ void test_initializeReadings_normal() assert(getSlidingWindowSize() == SLIDING_WINDOW_SIZE); } +/** + * @brief Test function to add readings to the data acquisition system. + * + * This function simulates adding readings to the data acquisition system + * for all sensors over a sliding window. It generates random values + * following a normal distribution with a specified mean and standard + * deviation, and adds these values as readings for each sensor. + * + * The function then asserts that the data acquisition system is full + * for the last sensor, indicating that readings have been successfully + * added for all sensors. + * + * @note This test assumes that the last sensor (NUMBER_OF_SENSORS - 1) + * has acquired the data. + */ void test_addReading_normal() { - for (int sensor = 0; sensor < NUMBER_OF_SENSORS; sensor++) + for (int i = 0; i < SLIDING_WINDOW_SIZE; i++) { - for (int i = 0; i < SLIDING_WINDOW_SIZE; i++) + for (int sensor = 0; sensor < NUMBER_OF_SENSORS; sensor++) { float u1 = (float)rand() / RAND_MAX; float u2 = (float)rand() / RAND_MAX; float z0 = sqrt(-2.0 * log(u1)) * cos(2.0 * M_PI * u2); float value = NORMAL_DISTRIBUTION_MEAN + z0 * NORMAL_DISTRIBUTION_STDDEV; - addReading(value, sensor); + addReading(value); } } assert(isFull(NUMBER_OF_SENSORS - 1) == true); // Assuming the last sensor acquired the data } +/** + * @brief Test the average value on a sensor under normal conditions. + * + * This function calculates the average value on the last sensor (NUMBER_OF_SENSORS - 1) + * and asserts that the difference between the calculated average and the expected mean + * (NORMAL_DISTRIBUTION_MEAN) is within an acceptable range defined by AVERAGE_UNCERTAINTY * 50. + * + * The test ensures that the average value on the sensor is within the expected range, + * indicating that the sensor data acquisition is functioning correctly under normal conditions. + */ void test_averageOnSensor_normal() { //printf("Average on sensor %d: %f\n", NUMBER_OF_SENSORS - 1, getAverageOnSensor(NUMBER_OF_SENSORS - 1)); @@ -144,41 +291,122 @@ void test_averageOnSensor_normal() assert(fabs(average - NORMAL_DISTRIBUTION_MEAN) < AVERAGE_UNCERTAINTY * 50); } +/** + * @brief Tests the standard deviation calculation on the last sensor. + * + * This function calculates the standard deviation for the last sensor + * and asserts that the calculated value is within an acceptable range + * of the expected standard deviation for a normal distribution. + * + * The acceptable range is defined as the expected standard deviation + * (NORMAL_DISTRIBUTION_STDDEV) plus or minus a tolerance (STD_UNCERTAINTY * 100). + * + * @note This test assumes that the sensor data follows a normal distribution. + */ void test_standardDeviationOnSensor_normal() { //printf("Standard deviation on sensor %d: %f\n", NUMBER_OF_SENSORS - 1, getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1)); float standard_deviation = getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1); - assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 50); + assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 100); } +/** + * @brief Test the average value calculation on all sensors under normal conditions. + * + * This function tests the `getAverageOnAllSensors` function to ensure that the + * average value calculated from all sensors is within an acceptable range of + * the expected normal distribution mean. The acceptable range is defined by + * `AVERAGE_UNCERTAINTY` multiplied by 100. + * + * The test asserts that the absolute difference between the calculated average + * and the expected normal distribution mean (`NORMAL_DISTRIBUTION_MEAN`) is + * less than the specified uncertainty range. + */ void test_averageOnAllSensors_normal() { //printf("Average on all sensors: %f\n", getAverageOnAllSensors()); float average = getAverageOnAllSensors(); - assert(fabs(average - NORMAL_DISTRIBUTION_MEAN) < AVERAGE_UNCERTAINTY * 50); + assert(fabs(average - NORMAL_DISTRIBUTION_MEAN) < AVERAGE_UNCERTAINTY * 100); } +/** + * @brief Test the standard deviation calculation on all sensors under normal conditions. + * + * This function tests the `getStandardDeviationOnAllSensors` function to ensure that the + * calculated standard deviation is within an acceptable range of the expected normal + * distribution standard deviation. The test asserts that the absolute difference between + * the calculated standard deviation and the expected normal distribution standard deviation + * is less than a specified uncertainty threshold. + * + * @note The expected normal distribution standard deviation is defined by the macro + * `NORMAL_DISTRIBUTION_STDDEV`, and the acceptable uncertainty is defined by the macro + * `STD_UNCERTAINTY`. + */ void test_standardDeviationOnAllSensors_normal() { //printf("Standard deviation on all sensors: %f\n", getStandardDeviationOnAllSensors()); float standard_deviation = getStandardDeviationOnAllSensors(); - assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 50); + assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 100); } +/** + * @brief Test the overall average calculation under normal conditions. + * + * This function tests the `getOverallAverage` function to ensure that the + * calculated average of all sensors is within an acceptable range of the + * expected normal distribution mean. The test asserts that the difference + * between the calculated average and the expected mean is less than a + * specified uncertainty threshold. + * + * @note The test uses the `fabs` function to compute the absolute difference + * between the calculated average and the expected mean. + */ void test_overallAverage_normal() { //printf("Overall average on all sensors: %f\n", getOverallAverage()); float average = getOverallAverage(); - assert(fabs(average - NORMAL_DISTRIBUTION_MEAN) < AVERAGE_UNCERTAINTY * 50); + assert(fabs(average - NORMAL_DISTRIBUTION_MEAN) < AVERAGE_UNCERTAINTY * 100); } +/** + * @brief Test the overall standard deviation for normal distribution. + * + * This function tests the standard deviation calculation for the last sensor + * in the array of sensors. It compares the calculated standard deviation + * with the expected standard deviation for a normal distribution. + * + * The test passes if the absolute difference between the calculated standard + * deviation and the expected standard deviation is less than the product of + * the standard uncertainty and 100. + * + * @note The function `getStandardDeviationOnSensor` is used to get the + * standard deviation for a specific sensor. + * + * @see getStandardDeviationOnSensor + */ void test_overallStandardDeviation_normal() { //printf("Overall standard deviation: %f\n", getOverallStandardDeviation()); float standard_deviation = getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1); - assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 50); + assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 100); } +/** + * @brief Tests the anomaly detection function under normal conditions. + * + * This function performs the following steps: + * 1. Calculates the overall average and standard deviation of the data. + * 2. Calls the anomaly detection function with the calculated average and standard deviation. + * 3. Asserts that the number of detected outliers is within the expected range (assuming 5% of the data is outliers). + * 4. Adds an outlier to the data. + * 5. Recalculates the overall average and standard deviation. + * 6. Calls the anomaly detection function again with the new average and standard deviation. + * 7. Asserts that the number of detected outliers has increased by one. + * + * The test assumes that the number of sensors and the sliding window size are defined by the constants + * NUMBER_OF_SENSORS and SLIDING_WINDOW_SIZE, respectively. It also assumes that the normal distribution + * mean is defined by the constant NORMAL_DISTRIBUTION_MEAN. + */ void test_anomalyDetect_normal() { float average = getOverallAverage(); @@ -188,7 +416,7 @@ void test_anomalyDetect_normal() assert(fabs(NUMBER_OF_SENSORS * SLIDING_WINDOW_SIZE * 0.05 >= getOutlierCount())); // Assuming 5% of the data is outliers // Adding an outlier - addReading(NORMAL_DISTRIBUTION_MEAN * 100, NUMBER_OF_SENSORS - 1); + addReading(NORMAL_DISTRIBUTION_MEAN * 100); average = getOverallAverage(); standard_deviation = getOverallStandardDeviation(); anomalyDetect(average, standard_deviation);