#include <Wire.h>
#include <MPU6050.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <math.h>
#include "time.h"
MPU6050 mpu;
// إعدادات الشبكة
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// إعدادات Firebase
const String FIREBASE_HOST = "https://iot-panel-protect-default-rtdb.europe-west1.firebasedatabase.app";
const String FIREBASE_API_KEY = "AIzaSyBh_Jq5_7PzrWbxIdGFaVVZtDdrj0v8yCc";
// المسارات في قاعدة البيانات
const String PATH_X = "/sensors/acceleration/x";
const String PATH_Y = "/sensors/acceleration/y";
const String PATH_Z = "/sensors/acceleration/z";
const String PATH_ADJ_X = "/sensors/adjusted/x";
const String PATH_ADJ_Y = "/sensors/adjusted/y";
const String PATH_ADJ_Z = "/sensors/adjusted/z";
const String PATH_STATUS = "/status/message";
const String PATH_LED_GREEN = "/leds/green";
const String PATH_LED_RED = "/leds/red";
const String PATH_LOG = "/log";
// تعريف الأرجل
#define BUZZER_PIN 15
#define LED_GREEN 13
#define LED_RED 12
// متغير لتتبع الحالة الأخيرة
String lastStatus = "";
// baseline لتعويض زاوية الميل 45 درجة حول محور X
const float baselineX = 0.707; // sin(45°)
const float baselineY = 0.0;
const float baselineZ = 0.707; // cos(45°)
// إعدادات خادم الوقت (NTP)
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3 * 3600; // UTC+3
const int daylightOffset_sec = 0;
// دالة لإرسال الأحداث مع طباعة للتصحيح
void logEvent(String message) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = FIREBASE_HOST + PATH_LOG + ".json?auth=" + FIREBASE_API_KEY;
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
return;
}
char timeString[30];
strftime(timeString, sizeof(timeString), "%Y-%m-%d %I:%M:%S %p", &timeinfo);
String json = "{\"message\":\"" + message + "\", \"timestamp\":\"" + String(timeString) + "\"}";
Serial.println("--> Logging new event to Firebase: " + json);
http.begin(url);
http.addHeader("Content-Type", "application/json");
http.POST(json);
http.end();
}
}
void setup() {
Serial.begin(115200);
Wire.begin();
mpu.initialize();
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, LOW);
Serial.println("MPU6050 initialized");
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi");
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
}
void loop() {
Serial.println("\n================ NEW READING ================");
int16_t ax, ay, az;
mpu.getAcceleration(&ax, &ay, &az);
float gx = ax / 16384.0;
float gy = ay / 16384.0;
float gz = az / 16384.0;
Serial.print("Raw Sensor Values: ");
Serial.print("X: "); Serial.print(gx, 3);
Serial.print(" | Y: "); Serial.print(gy, 3);
Serial.print(" | Z: "); Serial.println(gz, 3);
// حساب القيم المعوضة هنا
float adjX = gx - baselineX;
float adjY = gy - baselineY;
float adjZ = gz - baselineZ;
Serial.print("Adjusted Accel: X=");
Serial.print(adjX, 3);
Serial.print(" Y=");
Serial.print(adjY, 3);
Serial.print(" Z=");
Serial.println(adjZ, 3);
// تحديد الحالة بناءً على القيم المعوضة
String status = analyzeMotion(adjX, adjY, adjZ);
Serial.println("Calculated Status: " + status);
if (status != lastStatus) {
logEvent(status);
lastStatus = status;
}
// إرسال القيم الخام
sendData(PATH_X, gx);
sendData(PATH_Y, gy);
sendData(PATH_Z, gz);
// إرسال القيم المعوضة
sendData(PATH_ADJ_X, adjX);
sendData(PATH_ADJ_Y, adjY);
sendData(PATH_ADJ_Z, adjZ);
sendStatus(PATH_STATUS, status);
if (status == "NORMAL") {
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_RED, LOW);
sendLEDStatus(PATH_LED_GREEN, true);
sendLEDStatus(PATH_LED_RED, false);
} else {
digitalWrite(BUZZER_PIN, HIGH);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, HIGH);
sendLEDStatus(PATH_LED_GREEN, false);
sendLEDStatus(PATH_LED_RED, true);
}
delay(2000);
}
// دالة تحليل الحركة مع القيم المعوضة
String analyzeMotion(float adjX, float adjY, float adjZ) {
float totalAccel = sqrt(adjX * adjX + adjY * adjY + adjZ * adjZ);
if (totalAccel > 1.0) { // عتبة للصدمات أو السقوط
return "CRASH ";
} else if (abs(adjX) > 0.3 || abs(adjY) > 0.3) {
return "TAMPERING or MOVEMENT";
} else {
return "NORMAL";
}
}
// دوال إرسال البيانات إلى Firebase
void sendData(String path, float value) {
if (WiFi.status() == WL_CONNECTED) {
Serial.println("--> Sending to Firebase: " + path + " = " + String(value, 3));
HTTPClient http;
String url = FIREBASE_HOST + path + ".json?auth=" + FIREBASE_API_KEY;
String json = String(value, 3);
http.begin(url);
http.addHeader("Content-Type", "application/json");
http.PUT(json);
http.end();
}
}
void sendStatus(String path, String message) {
if (WiFi.status() == WL_CONNECTED) {
Serial.println("--> Sending to Firebase: " + path + " = " + message);
HTTPClient http;
String url = FIREBASE_HOST + path + ".json?auth=" + FIREBASE_API_KEY;
String json = "\"" + message + "\"";
http.begin(url);
http.addHeader("Content-Type", "application/json");
http.PUT(json);
http.end();
}
}
void sendLEDStatus(String path, bool isOn) {
if (WiFi.status() == WL_CONNECTED) {
String statusStr = isOn ? "true" : "false";
Serial.println("--> Sending to Firebase: " + path + " = " + statusStr);
HTTPClient http;
String url = FIREBASE_HOST + path + ".json?auth=" + FIREBASE_API_KEY;
String json = isOn ? "true" : "false";
http.begin(url);
http.addHeader("Content-Type", "application/json");
http.PUT(json);
http.end();
}
}