diff --git a/TP3/src/main.cpp b/TP3/src/main.cpp index 18fdf31..65302ec 100644 --- a/TP3/src/main.cpp +++ b/TP3/src/main.cpp @@ -1,21 +1,25 @@ - #include "DHT.h" + #define DHTPIN 2 // Digital pin connected to the DHT sensor -#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 +#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 DHT dht(DHTPIN, DHTTYPE); -const int N_FEATURES = 12; -const float MEAN[N_FEATURES] = {/* μ_Temperature, μ_Humidity */}; -const float STD[N_FEATURES] = {/* σ_Temperature, σ_Humidity */}; -const float WEIGHTS[N_FEATURES] = {/* W_Temperature, W_Humidity */}; -const float BIAS = 0; /* b */ +const int N_FEATURES = 2; // فقط الحرارة والرطوبة في المثال + +// إحصائيات البيانات (قيم تجريبية افتراضية) +const float MEAN[N_FEATURES] = {25.0, 60.0}; // المتوسط +const float STD[N_FEATURES] = {5.0, 10.0}; // الانحراف المعياري -float X[N_FEATURES] = {20.0, 57.36, 0, 400, 12306, 18520, 939.735, 0.0, 0.0, 0.0, 0.0, 0.0}; // Input features +// الأوزان والانحياز (افتراضية كمثال) +const float WEIGHTS[N_FEATURES] = {0.3, -0.2}; +const float BIAS = 0.5; + +float X[N_FEATURES]; void setup() { Serial.begin(9600); - Serial.println(F("DHTxx test!")); + Serial.println(F("DHT22 test + ML model!")); dht.begin(); } @@ -23,47 +27,40 @@ void loop() { delay(2000); - // Reading temperature or humidity takes about 250 milliseconds! - // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) float h = dht.readHumidity(); - // Read temperature as Celsius (the default) float t = dht.readTemperature(); - // Read temperature as Fahrenheit (isFahrenheit = true) - float f = dht.readTemperature(true); - // add data to input array - X[0] = t; - X[1] = h; - - // Check if any reads failed and exit early (to try again). - if (isnan(h) || isnan(t) || isnan(f)) + if (isnan(h) || isnan(t)) { Serial.println(F("Failed to read from DHT sensor!")); return; } - // TODO: Add code to standardize the inputs - - // TODO: Add code to compute the output of wx + b + X[0] = t; + X[1] = h; - // TODO: Add code to apply the sigmoid function + // 1️⃣ توحيد القيم (Standardization) + float X_std[N_FEATURES]; + for (int i = 0; i < N_FEATURES; i++) + { + X_std[i] = (X[i] - MEAN[i]) / STD[i]; + } - // TODO: Add code to print the result to the serial monitor + // 2️⃣ حساب wx + b + float linear = BIAS; + for (int i = 0; i < N_FEATURES; i++) + { + linear += WEIGHTS[i] * X_std[i]; + } - // Compute heat index in Fahrenheit (the default) - // float hif = dht.computeHeatIndex(f, h); - // Compute heat index in Celsius (isFahreheit = false) - // float hic = dht.computeHeatIndex(t, h, false); + // 3️⃣ تطبيق دالة sigmoid + float sigmoid = 1.0 / (1.0 + exp(-linear)); - Serial.print("Humidity: "); - Serial.print(h); - Serial.print("% Tempeature: "); + // 4️⃣ طباعة النتائج + Serial.print("Temp: "); Serial.print(t); - Serial.print("°C "); - Serial.println(f); - // Serial.print(F("°F Heat index: ")); - // Serial.print(hic); - // Serial.print(F("°C ")); - // Serial.print(hif); - // Serial.println(F("°F")); -} \ No newline at end of file + Serial.print("°C Humidity: "); + Serial.print(h); + Serial.print("% -> Model Output: "); + Serial.println(sigmoid, 4); // 4 منازل عشرية +} diff --git a/TP4/ai_logic/mqtt_ai_subscriber.py b/TP4/ai_logic/mqtt_ai_subscriber.py index 17c19bc..417b30a 100644 --- a/TP4/ai_logic/mqtt_ai_subscriber.py +++ b/TP4/ai_logic/mqtt_ai_subscriber.py @@ -1,15 +1,79 @@ -import json, paho.mqtt.client as mqtt +import json +import pickle +import paho.mqtt.client as mqtt -def on_message(client, userdata, msg): - data = json.loads(msg.payload) - print(f"Received: {data}") - if data["temperature"] > 30: - client.publish("esp32/control", "ON") +# === تحميل النموذجين === +with open("../models/model_lr.pkl", "rb") as f: + model_lr = pickle.load(f) + +with open("../models/model_xgb.pkl", "rb") as f: + model_xgb = pickle.load(f) + + +# النموذج الحالي المستخدم +current_model = "lr" +models = {"lr": model_lr, "xgb": model_xgb} + +print("✅ Models loaded successfully (LR + XGB)") +print("🧠 Current model:", current_model) + +# === دالة التبديل بين النماذج === +def switch_model(new_model): + global current_model + if new_model in models: + current_model = new_model + print(f"🔁 Model switched to: {new_model}") else: - client.publish("esp32/control", "OFF") + print(f"⚠️ Unknown model: {new_model}") + +# === عند استقبال رسالة === +def on_message(client, userdata, msg): + global current_model + + topic = msg.topic + payload = msg.payload.decode("utf-8") + + # إذا كانت رسالة التحكم بالنموذج + if topic == "esp32/model": + switch_model(payload.strip()) + return + + # رسائل البيانات من Arduino + if topic == "esp32/data": + try: + data = json.loads(payload) + temp = data.get("temperature") + humid = data.get("humidity") + if temp is None or humid is None: + print("⚠️ Missing temperature/humidity in data.") + return + + # تجهيز الإدخال للنموذج + X = [[temp, humid]] + model = models[current_model] + pred = model.predict(X)[0] + + # إرسال القرار إلى ESP32 + command = "ON" if pred == 1 else "OFF" + print(f"📩 Data: T={temp:.1f}°C, H={humid:.1f}% → Model={current_model} → {command}") + client.publish("esp32/control", command) + + except Exception as e: + print("❌ Error handling message:", e) + +# === إعداد MQTT === client = mqtt.Client() -client.connect("broker.mqtt.cool", 1883, 60) -client.subscribe("esp32/data") client.on_message = on_message + +broker = "broker.mqtt.cool" +port = 1883 + +client.connect(broker, port, 60) +client.subscribe("esp32/data") +client.subscribe("esp32/model") # لتبديل النموذج + +print(f"🚀 Connected to MQTT broker at {broker}:{port}") +print("📡 Listening for data...") + client.loop_forever() diff --git a/TP4/createmodel.py b/TP4/createmodel.py new file mode 100644 index 0000000..fc8e0c7 --- /dev/null +++ b/TP4/createmodel.py @@ -0,0 +1,47 @@ +# === create_models.py === +import os +import pickle +import numpy as np +from sklearn.linear_model import LogisticRegression +from xgboost import XGBClassifier +from sklearn.model_selection import train_test_split +from sklearn.metrics import accuracy_score + +# إنشاء مجلد models إذا لم يكن موجودًا +os.makedirs("models", exist_ok=True) + +# توليد بيانات تجريبية (حرارة ورطوبة) +# الهدف هنا تصنيف حالة الطقس مثلاً (0 = عادي، 1 = خطر) +np.random.seed(42) +temp = np.random.uniform(15, 40, 200) # حرارة بين 15 و40 +humid = np.random.uniform(20, 90, 200) # رطوبة بين 20 و90 +labels = (temp > 30) & (humid > 60) # إذا الحرارة >30 والرطوبة >60 = خطر +labels = labels.astype(int) + +X = np.column_stack((temp, humid)) +y = labels + +# تقسيم البيانات +X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) + +# --- نموذج Logistic Regression --- +model_lr = LogisticRegression() +model_lr.fit(X_train, y_train) +y_pred_lr = model_lr.predict(X_test) +print("Logistic Regression Accuracy:", accuracy_score(y_test, y_pred_lr)) + +# حفظ النموذج +with open("models/model_lr.pkl", "wb") as f: + pickle.dump(model_lr, f) + +# --- نموذج XGBoost --- +model_xgb = XGBClassifier(use_label_encoder=False, eval_metric='logloss') +model_xgb.fit(X_train, y_train) +y_pred_xgb = model_xgb.predict(X_test) +print("XGBoost Accuracy:", accuracy_score(y_test, y_pred_xgb)) + +# حفظ النموذج +with open("models/model_xgb.pkl", "wb") as f: + pickle.dump(model_xgb, f) + +print("\n✅ تم إنشاء النموذجين model_lr.pkl و model_xgb.pkl داخل مجلد models") diff --git a/TP4/image.png b/TP4/image.png new file mode 100644 index 0000000..914c17b Binary files /dev/null and b/TP4/image.png differ diff --git a/TP4/models/model_lr.pkl b/TP4/models/model_lr.pkl new file mode 100644 index 0000000..d3733c0 Binary files /dev/null and b/TP4/models/model_lr.pkl differ diff --git a/TP4/models/model_xgb.pkl b/TP4/models/model_xgb.pkl new file mode 100644 index 0000000..622992f Binary files /dev/null and b/TP4/models/model_xgb.pkl differ diff --git a/TP4/src/main.cpp b/TP4/src/main.cpp index 02be143..014e138 100644 --- a/TP4/src/main.cpp +++ b/TP4/src/main.cpp @@ -1,5 +1,3 @@ - - #include #include #include @@ -13,87 +11,70 @@ const char *ssid = "Wokwi-GUEST"; const char *password = ""; -// MQTT broker (local machine IP) -const char *mqtt_server = "broker.mqtt.cool"; // or your LAN IP, e.g. "192.168.1.100" +// MQTT broker +const char *mqtt_server = "broker.mqtt.cool"; const int mqtt_port = 1883; WiFiClient espClient; PubSubClient client(espClient); DHT dht(DHTPIN, DHTTYPE); -LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD address 0x27 or 0x3F -String currentCommand = "---"; // default command - -const int N_FEATURES = 12; -float X[N_FEATURES] = {20.0, 57.36, 0, 400, 12306, 18520, 939.735, 0.0, 0.0, 0.0, 0.0, 0.0}; // Input features +LiquidCrystal_I2C lcd(0x27, 16, 2); +String currentCommand = "---"; -void setup_wifi() -{ +void setup_wifi() { Serial.println("Connecting to WiFi..."); WiFi.begin(ssid, password); - while (WiFi.status() != WL_CONNECTED) - { + while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } - Serial.println("\nWiFi connected!"); + Serial.println("\n✅ WiFi connected!"); } -void callback(char *topic, byte *message, unsigned int length) -{ +void callback(char *topic, byte *message, unsigned int length) { String msg; - for (int i = 0; i < length; i++) - msg += (char)message[i]; + for (int i = 0; i < length; i++) msg += (char)message[i]; msg.trim(); - Serial.print("Received command: "); + Serial.print("📥 Command received: "); Serial.println(msg); - if (msg.equalsIgnoreCase("ON")) - { + if (msg.equalsIgnoreCase("ON")) { digitalWrite(LED_PIN, HIGH); currentCommand = "ON"; - } - else if (msg.equalsIgnoreCase("OFF")) - { + } else if (msg.equalsIgnoreCase("OFF")) { digitalWrite(LED_PIN, LOW); currentCommand = "OFF"; } - // Update the LCD immediately when a command arrives + // تحديث الشاشة lcd.setCursor(0, 1); lcd.print("CMD:"); lcd.print(currentCommand); - lcd.print(" "); // clear any leftover characters + lcd.print(" "); } -void reconnect() -{ - while (!client.connected()) - { - Serial.print("Attempting MQTT connection..."); - if (client.connect("ESP32Client")) - { - Serial.println("connected"); +void reconnect() { + while (!client.connected()) { + Serial.print("Connecting to MQTT..."); + if (client.connect("ESP32Client")) { + Serial.println(" connected!"); client.subscribe("esp32/control"); - } - else - { - Serial.print("failed, rc="); + } else { + Serial.print(" failed, rc="); Serial.print(client.state()); - Serial.println(" retrying in 5s"); + Serial.println(" retry in 5s"); delay(5000); } } } -void setup() -{ +void setup() { Serial.begin(115200); pinMode(LED_PIN, OUTPUT); lcd.init(); lcd.backlight(); - lcd.clear(); - lcd.print("Starting..."); + lcd.print("Booting..."); dht.begin(); setup_wifi(); @@ -102,30 +83,25 @@ void setup() } unsigned long lastMsg = 0; -const long interval = 3000; // update every 3 seconds +const long interval = 3000; -void loop() -{ - if (!client.connected()) - reconnect(); +void loop() { + if (!client.connected()) reconnect(); client.loop(); unsigned long now = millis(); - if (now - lastMsg > interval) - { + if (now - lastMsg > interval) { lastMsg = now; float h = dht.readHumidity(); float t = dht.readTemperature(); - if (isnan(h) || isnan(t)) - return; + if (isnan(h) || isnan(t)) return; - // add data to input array - - X[0] = t; - X[1] = h; + // إرسال البيانات إلى Python + String payload = "{\"temperature\": " + String(t, 1) + ", \"humidity\": " + String(h, 1) + "}"; + client.publish("esp32/data", payload.c_str()); - // Update LCD with temperature and humidity + // عرض القيم lcd.setCursor(0, 0); lcd.print("T:"); lcd.print(t, 1); @@ -133,14 +109,6 @@ void loop() lcd.print(h, 0); lcd.print("% "); - // Update the command line - lcd.setCursor(0, 1); - lcd.print("CMD:"); - lcd.print(currentCommand); - lcd.print(" "); - - // TODO: Publish all features to MQTT - String payload = "{\"temperature\": " + String(t) + ", \"humidity\": " + String(h) + "}"; - client.publish("esp32/data", payload.c_str()); + Serial.println("📤 Sent: " + payload); } }