#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ThingSpeak.h>
#include <HTTPClient.h>
// إعدادات الشبكة
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// إعدادات MQTT
const char* mqttServer = "mqtt3.thingspeak.com";
const int mqttPort = 1883;
const char* mqttClientID = "Kww0KyIDPTASAgU7NRQxMDI";
const char* mqttUsername = "Kww0KyIDPTASAgU7NRQxMDI";
const char* mqttPassword = "XWQDo423GHt1/UVHObDawHbo";
// إعدادات القنوات
const unsigned long SENSORS_CHANNEL_ID = 3064682;
const char* SENSORS_WRITE_API_KEY = "WPK7MNS2DYHPPHTP";
const unsigned long CONTROL_CHANNEL_ID = 3064684;
const char* CONTROL_WRITE_API_KEY = "Y1A0HF8HJ3VFKFLT";
WiFiClient client;
PubSubClient mqttClient(client);
// تعريف الدبابيس
#define DHT_PIN 15
#define FAN_PIN 12
#define HEATER_PIN 14
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
// مواضيع MQTT
char sensorsPublishTopic[50];
char fanControlTopic[50];
char heaterControlTopic[50];
char controlPublishTopic[50]; // تم إضافة topic للإرسال إلى قناة التحكم
unsigned long lastPublishTime = 0;
const unsigned long publishInterval = 20000;
// ===============================================
// دالة الإرسال إلى قناة التحكم (المضافة)
// ===============================================
void sendToControlChannel(int fieldNumber, int value) {
String dataString = "field" + String(fieldNumber) + "=" + String(value);
if (mqttClient.publish(controlPublishTopic, dataString.c_str())) {
Serial.print("📤 Sent to control channel: ");
Serial.println(dataString);
} else {
Serial.println("❌ Failed to send to control channel via MQTT");
// Fallback إلى HTTP
HTTPClient http;
String url = "http://api.thingspeak.com/update?api_key=" +
String(CONTROL_WRITE_API_KEY) +
"&field" + String(fieldNumber) + "=" + String(value);
http.begin(url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
Serial.println("✅ Control data sent via HTTP");
} else {
Serial.print("❌ HTTP control update failed. Error code: ");
Serial.println(httpCode);
}
http.end();
}
}
// ===============================================
// دالة معالجة الرسائل الواردة (Callback)
// ===============================================
void mqttCallback(char* topic, byte* payload, unsigned int length) {
// إضافة null terminator للبيانات الواردة
payload[length] = '\0';
String message = String((char*)payload);
String topicStr = String(topic);
Serial.print("📨 Message arrived [");
Serial.print(topicStr);
Serial.print("]: ");
Serial.println(message);
// التحكم في المروحة (Field1)
if (topicStr.indexOf("field1") != -1) {
if (message == "1") {
digitalWrite(FAN_PIN, HIGH);
Serial.println("✅ Fan turned ON");
// إرسال تأكيد إلى قناة التحكم
sendToControlChannel(1, 1);
} else if (message == "0") {
digitalWrite(FAN_PIN, LOW);
Serial.println("✅ Fan turned OFF");
// إرسال تأكيد إلى قناة التحكم
sendToControlChannel(1, 0);
}
}
// التحكم في السخان (Field2)
if (topicStr.indexOf("field2") != -1) {
if (message == "1") {
digitalWrite(HEATER_PIN, HIGH);
Serial.println("✅ Heater turned ON");
// إرسال تأكيد إلى قناة التحكم
sendToControlChannel(2, 1);
} else if (message == "0") {
digitalWrite(HEATER_PIN, LOW);
Serial.println("✅ Heater turned OFF");
// إرسال تأكيد إلى قناة التحكم
sendToControlChannel(2, 0);
}
}
}
// ===============================================
// بداية دالة setup
// ===============================================
void setup() {
Serial.begin(115200);
dht.begin();
pinMode(FAN_PIN, OUTPUT);
pinMode(HEATER_PIN, OUTPUT);
digitalWrite(FAN_PIN, LOW);
digitalWrite(HEATER_PIN, LOW);
// الاتصال بالواي فاي
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("✅ Connected to WiFi");
// إعداد MQTT
mqttClient.setServer(mqttServer, mqttPort);
mqttClient.setCallback(mqttCallback);
// إنشاء مواضيع MQTT بشكل صحيح
sprintf(sensorsPublishTopic, "channels/%ld/publish", SENSORS_CHANNEL_ID);
sprintf(fanControlTopic, "channels/%ld/subscribe/fields/field1", CONTROL_CHANNEL_ID);
sprintf(heaterControlTopic, "channels/%ld/subscribe/fields/field2", CONTROL_CHANNEL_ID);
sprintf(controlPublishTopic, "channels/%ld/publish", CONTROL_CHANNEL_ID); // topic للإرسال
// معلومات التحقق
Serial.print("Control Channel ID: ");
Serial.println(CONTROL_CHANNEL_ID);
Serial.print("Control Publish Topic: ");
Serial.println(controlPublishTopic);
Serial.println("System initialized. Connecting to MQTT...");
connectToMQTT();
}
// ===============================================
// دالة الحفاظ على الاتصال MQTT
// ===============================================
void maintainMQTTConnection() {
if (!mqttClient.connected()) {
Serial.println("⚠️ MQTT connection lost. Reconnecting...");
connectToMQTT();
}
mqttClient.loop(); // ضروري لمعالجة الرسائل الواردة
}
// ===============================================
// بداية دالة loop
// ===============================================
void loop() {
maintainMQTTConnection();
// قراءة وإرسال البيانات كل 20 ثانية
unsigned long currentTime = millis();
if (currentTime - lastPublishTime >= publishInterval) {
readAndSendSensorData();
lastPublishTime = currentTime;
}
delay(100); // إضافة delay صغيرة لاستقرار النظام
}
// ===============================================
// دالة الاتصال بـ MQTT Broker
// ===============================================
void connectToMQTT() {
int retryCount = 0;
while (!mqttClient.connected() && retryCount < 5) {
Serial.print("🔗 Attempting MQTT connection...");
if (mqttClient.connect(mqttClientID, mqttUsername, mqttPassword)) {
Serial.println("✅ connected");
// الاشتراك في مواضيع التحكم مع التحقق من النجاح
if (mqttClient.subscribe(fanControlTopic)) {
Serial.println("✓ Subscribed to fan control");
} else {
Serial.println("✗ Fan subscription failed!");
}
if (mqttClient.subscribe(heaterControlTopic)) {
Serial.println("✓ Subscribed to heater control");
} else {
Serial.println("✗ Heater subscription failed!");
}
// طباعة المواضيع للتحقق
Serial.print("Fan Subscribe Topic: ");
Serial.println(fanControlTopic);
Serial.print("Heater Subscribe Topic: ");
Serial.println(heaterControlTopic);
Serial.print("Control Publish Topic: ");
Serial.println(controlPublishTopic);
} else {
Serial.print("❌ failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 2 seconds");
delay(2000);
retryCount++;
}
}
if (retryCount >= 5) {
Serial.println("🛑 MQTT connection failed after 5 attempts");
}
}
// ===============================================
// دالة قراءة وإرسال بيانات المستشعر
// ===============================================
void readAndSendSensorData() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) {
Serial.println("❌ Failed to read from DHT sensor!");
return;
}
Serial.print("🌡️ Temperature: ");
Serial.print(temperature);
Serial.print("°C, 💧 Humidity: ");
Serial.print(humidity);
Serial.println("%");
String dataString = "field1=" + String(temperature) + "&field2=" + String(humidity);
if (mqttClient.publish(sensorsPublishTopic, dataString.c_str())) {
Serial.println("📤 Data published via MQTT: " + dataString);
} else {
Serial.println("❌ MQTT publish failed!");
sendDataViaHTTP(temperature, humidity);
}
}
// ===============================================
// دالة إرسال البيانات عبر HTTP (نسخة احتياطية)
// ===============================================
void sendDataViaHTTP(float temperature, float humidity) {
HTTPClient http;
String url = "http://api.thingspeak.com/update?api_key=" +
String(SENSORS_WRITE_API_KEY) +
"&field1=" + String(temperature) +
"&field2=" + String(humidity);
http.begin(url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
Serial.println("✅ ThingSpeak update successful via HTTP.");
} else {
Serial.print("❌ ThingSpeak update failed. Error code: ");
Serial.println(httpCode);
}
http.end();
}