2024-11-20 00:50:35 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
2024-11-21 16:35:08 +01:00
|
|
|
int outlierCount;
|
|
|
|
|
|
2024-11-20 00:50:35 +01:00
|
|
|
// Variable definition
|
|
|
|
|
static float **readings;
|
2024-11-20 01:26:04 +01:00
|
|
|
static int sensorsNumber;
|
|
|
|
|
static int slidingWindowSize;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void setSensorsNumber(int number) {
|
|
|
|
|
sensorsNumber = number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void setSlidingWindowSize(int size) {
|
|
|
|
|
slidingWindowSize = size;
|
|
|
|
|
}
|
2024-11-20 00:50:35 +01:00
|
|
|
|
|
|
|
|
void initializeReadings(int numSensors, int windowSize) {
|
|
|
|
|
readings = (float **)malloc(numSensors * sizeof(float *));
|
|
|
|
|
if (readings == NULL) {
|
|
|
|
|
perror("Failed to allocate memory for readings");
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < numSensors; i++) {
|
|
|
|
|
readings[i] = (float *)calloc(windowSize, sizeof(float));
|
|
|
|
|
if (readings[i] == NULL) {
|
|
|
|
|
perror("Failed to allocate memory for sensor readings");
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-20 01:26:04 +01:00
|
|
|
// Chiamate private ai setter
|
2024-11-20 00:50:35 +01:00
|
|
|
setSensorsNumber(numSensors);
|
|
|
|
|
setSlidingWindowSize(windowSize);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-21 16:35:08 +01:00
|
|
|
bool freeReadings() {
|
2024-11-20 00:50:35 +01:00
|
|
|
for (int i = 0; i < sensorsNumber; i++) {
|
|
|
|
|
free(readings[i]);
|
|
|
|
|
}
|
2024-11-21 16:35:08 +01:00
|
|
|
|
|
|
|
|
if(readings != NULL){
|
|
|
|
|
free(readings);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-20 00:50:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Functions
|
|
|
|
|
|
|
|
|
|
// Get the number of sensors
|
|
|
|
|
int getSensorsNumber() {
|
|
|
|
|
return sensorsNumber;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the sliding window size
|
|
|
|
|
int getSlidingWindowSize() {
|
|
|
|
|
return slidingWindowSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Control on the fullness of the sliding window
|
|
|
|
|
bool isFull(int sensorIndex) {
|
|
|
|
|
for (int i = 0; i < slidingWindowSize; i++) {
|
|
|
|
|
if (readings[sensorIndex][i] == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-21 16:35:08 +01:00
|
|
|
float getLastReading(int sensorIndex) {
|
|
|
|
|
if (isFull(sensorIndex)) {
|
|
|
|
|
return readings[sensorIndex][slidingWindowSize - 1];
|
|
|
|
|
} else {
|
|
|
|
|
return readings[sensorIndex][0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-20 00:50:35 +01:00
|
|
|
// Add a reading to the readings array
|
|
|
|
|
void addReading(float value, int sensorIndex) {
|
|
|
|
|
if (isFull(sensorIndex)) {
|
|
|
|
|
for (int i = 0; i < slidingWindowSize - 1; i++) {
|
|
|
|
|
readings[sensorIndex][i] = readings[sensorIndex][i + 1];
|
|
|
|
|
}
|
|
|
|
|
readings[sensorIndex][slidingWindowSize - 1] = value;
|
|
|
|
|
} else {
|
|
|
|
|
for (int i = 0; i < slidingWindowSize; i++) {
|
|
|
|
|
if (readings[sensorIndex][i] == 0) {
|
|
|
|
|
readings[sensorIndex][i] = value;
|
2024-11-21 16:35:08 +01:00
|
|
|
// Update the position index
|
|
|
|
|
|
2024-11-20 00:50:35 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float getAverageOnSensor(int sensorIndex) {
|
|
|
|
|
if(isFull(sensorIndex) == false){
|
|
|
|
|
printf("The sliding window is not full\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
float sum = 0;
|
|
|
|
|
for (int i = 0; i < slidingWindowSize; i++) {
|
|
|
|
|
sum += readings[sensorIndex][i];
|
|
|
|
|
}
|
|
|
|
|
return sum / slidingWindowSize;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float getAverageOnAllSensors() {
|
|
|
|
|
float sum = 0;
|
|
|
|
|
for (int i = 0; i < sensorsNumber; i++) {
|
2024-11-21 16:35:08 +01:00
|
|
|
sum += getLastReading(i);
|
2024-11-20 00:50:35 +01:00
|
|
|
}
|
|
|
|
|
return sum / sensorsNumber;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float getOverallAverage() {
|
|
|
|
|
float sum = 0;
|
|
|
|
|
int totalReadings = 0;
|
|
|
|
|
for (int i = 0; i < sensorsNumber; i++) {
|
|
|
|
|
if (!isFull(i)) {
|
|
|
|
|
printf("The sliding window for sensor %d is not full\n", i);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
for (int j = 0; j < slidingWindowSize; j++) {
|
|
|
|
|
sum += readings[i][j];
|
|
|
|
|
totalReadings++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return sum / totalReadings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float getStandardDeviationOnSensor(int sensorIndex) {
|
|
|
|
|
if(isFull(sensorIndex) == false){
|
|
|
|
|
printf("The sliding window is not full\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
float sum = 0;
|
|
|
|
|
float average = getAverageOnSensor(sensorIndex);
|
|
|
|
|
for (int i = 0; i < slidingWindowSize; i++) {
|
|
|
|
|
sum += pow(readings[sensorIndex][i] - average, 2);
|
|
|
|
|
}
|
|
|
|
|
return sqrt(sum / slidingWindowSize);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float getStandardDeviationOnAllSensors() {
|
|
|
|
|
float sum = 0;
|
2024-11-21 16:35:08 +01:00
|
|
|
float average = getAverageOnAllSensors();
|
2024-11-20 00:50:35 +01:00
|
|
|
for (int i = 0; i < sensorsNumber; i++) {
|
2024-11-21 16:35:08 +01:00
|
|
|
float lastReading = getLastReading(i);
|
|
|
|
|
sum += pow(lastReading - average, 2);
|
2024-11-20 00:50:35 +01:00
|
|
|
}
|
2024-11-21 16:35:08 +01:00
|
|
|
|
|
|
|
|
return sqrt(sum / sensorsNumber);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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++) {
|
|
|
|
|
if (readings[i][j] > upperThreshold || readings[i][j] < lowerThreshold) {
|
|
|
|
|
outlierCount++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-20 00:50:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float getOverallStandardDeviation() {
|
|
|
|
|
float sum = 0;
|
|
|
|
|
int totalReadings = 0;
|
2024-11-21 16:35:08 +01:00
|
|
|
float totalAverage = getOverallAverage();
|
2024-11-20 00:50:35 +01:00
|
|
|
for (int i = 0; i < sensorsNumber; i++) {
|
|
|
|
|
if (!isFull(i)) {
|
|
|
|
|
printf("The sliding window for sensor %d is not full\n", i);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
for (int j = 0; j < slidingWindowSize; j++) {
|
|
|
|
|
sum += pow(readings[i][j] - getOverallAverage(), 2);
|
|
|
|
|
totalReadings++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-21 16:35:08 +01:00
|
|
|
|
|
|
|
|
float totalStandardDeviation = sqrt(sum / totalReadings);
|
|
|
|
|
|
|
|
|
|
anomalyDetect(totalAverage, totalStandardDeviation);
|
|
|
|
|
|
|
|
|
|
return totalStandardDeviation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int getOutlierCount() {
|
|
|
|
|
return outlierCount;
|
2024-11-20 00:50:35 +01:00
|
|
|
}
|