#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
// تعريف منافذ التوصيل
#define DHT_PIN 15 // منفذ توصيل DHT22 (GPIO15)
#define FAN_LED_PIN 12 // LED أزرق للمروحة (GPIO12)
#define HEATER_LED_PIN 14 // LED أحمر للسخان (GPIO14)
#define STATUS_LED_PIN 13 // LED مؤشر حالة النظام (GPIO13) - كوشر بصري
#define DHT_TYPE DHT22
// بيانات شبكة WiFi الافتراضية (شبكة تجريبية)
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// ==================== إعدادات ThingSpeak ====================
// بيانات MQTT لـ ThingSpeak
const char* mqtt_server = "mqtt3.thingspeak.com"; // تغيير السيرفر
const int mqtt_port = 1883;
// معلومات القنوات (يجب استبدالها بمعلوماتك)
unsigned long SENSORS_CHANNEL_ID = 3064936; // استبدل برقم قناة الاستشعار
unsigned long CONTROL_CHANNEL_ID = 3064937; // استبدل برقم قناة التحكم
const char* mqttClientID = "Ez0iOxoDFjECACw4HAkfISU"; // استبدل بـ Client ID
const char* mqttUsername = "Ez0iOxoDFjECACw4HAkfISU"; // استبدل بـ Username
const char* mqttPassword = "8gBiSHUlJWrYVPU+KsNf2OR4"; // استبدل بـ Password
// مواضيع MQTT لـ ThingSpeak
char mqtt_publish_topic[50];
char mqtt_subscribe_topic[50];
// ==================== إعدادات原有的 ====================
const char* mqtt_topic_temp = "greenhouse/temperature";
const char* mqtt_topic_humidity = "greenhouse/humidity";
const char* mqtt_topic_status = "greenhouse/status";
// إنشاء الكائنات
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHT_PIN, DHT_TYPE);
// تعريف عتبات الحرارة
const float MIN_TEMP = 18.0;
const float MAX_TEMP = 25.0;
// متغيرات التوقيت
unsigned long lastMsg = 0;
unsigned long lastBlink = 0;
unsigned long lastThingSpeakUpdate = 0;
const long interval = 5000; // إرسال البيانات كل 5 ثواني
const long blinkInterval = 500; // وميض LED كل 500 مللي ثانية
const long thingspeakInterval = 15000; // ThingSpeak يحدد 15 ثانية بين كل إرسال
// متغيرات للبيانات
float temperature = 0;
float humidity = 0;
bool statusLedState = LOW;
int blinkPattern = 0; // نمط الوميض: 0=اكتشاف شبكة، 1=اتصال MQTT، 2=عمل طبيعي
int fanStatus = 0;
int heaterStatus = 0;
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
// بدء نمط اكتشاف الشبكة (وميض سريع)
blinkPattern = 0;
// محاولة الاتصال بالشبكة المحددة
WiFi.begin(ssid, password);
// إذا فشل الاتصال، إنشاء نقطة وصول (AP)
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("");
Serial.println("Could not connect to WiFi. Creating access point...");
// إنشاء نقطة وصول (AP)
WiFi.softAP("Greenhouse_AP", "12345678");
Serial.println("Access Point created");
Serial.print("AP IP address: ");
Serial.println(WiFi.softAPIP());
// تغيير نمط الوميض لنقطة الوصول
blinkPattern = 1;
} else {
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// تغيير نمط الوميض للاتصال الناجح
blinkPattern = 2;
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.println(message);
// وميض سريع عند استقبال أي رسالة
digitalWrite(STATUS_LED_PIN, HIGH);
delay(100);
digitalWrite(STATUS_LED_PIN, LOW);
delay(100);
digitalWrite(STATUS_LED_PIN, HIGH);
delay(100);
digitalWrite(STATUS_LED_PIN, LOW);
// ==================== معالجة أوامر ThingSpeak ====================
if (String(topic).indexOf("field1") != -1) {
if (message == "1") {
analogWrite(FAN_LED_PIN, 200);
fanStatus = 1;
Serial.println("Fan turned ON by ThingSpeak command");
} else if (message == "0") {
analogWrite(FAN_LED_PIN, 0);
fanStatus = 0;
Serial.println("Fan turned OFF by ThingSpeak command");
}
}
if (String(topic).indexOf("field2") != -1) {
if (message == "1") {
analogWrite(HEATER_LED_PIN, 200);
heaterStatus = 1;
Serial.println("Heater turned ON by ThingSpeak command");
} else if (message == "0") {
analogWrite(HEATER_LED_PIN, 0);
heaterStatus = 0;
Serial.println("Heater turned OFF by ThingSpeak command");
}
}
// ==================== معالجة الأوامر الأصلية ====================
if (String(topic) == "greenhouse/control/fan") {
if (message == "ON") {
analogWrite(FAN_LED_PIN, 200);
fanStatus = 1;
Serial.println("Fan turned ON by MQTT command");
} else if (message == "OFF") {
analogWrite(FAN_LED_PIN, 0);
fanStatus = 0;
Serial.println("Fan turned OFF by MQTT command");
}
}
if (String(topic) == "greenhouse/control/heater") {
if (message == "ON") {
analogWrite(HEATER_LED_PIN, 200);
heaterStatus = 1;
Serial.println("Heater turned ON by MQTT command");
} else if (message == "OFF") {
analogWrite(HEATER_LED_PIN, 0);
heaterStatus = 0;
Serial.println("Heater turned OFF by MQTT command");
}
}
}
void reconnect() {
// تغيير نمط الوميض أثناء محاولة الاتصال
blinkPattern = 3;
while (!client.connected()) {
Serial.print("Attempting MQTT connection to ThingSpeak...");
// استخدام بيانات اعتماد ThingSpeak
if (client.connect(mqttClientID, mqttUsername, mqttPassword)) {
Serial.println("connected");
// نشر رسالة اتصال
client.publish(mqtt_topic_status, "Greenhouse system connected to ThingSpeak");
// الاشتراك في مواضيع التحكم الأصلية
client.subscribe("greenhouse/control/fan");
client.subscribe("greenhouse/control/heater");
// الاشتراك في مواضيع تحكم ThingSpeak
sprintf(mqtt_subscribe_topic, "channels/%lu/subscribe/fields/field1", CONTROL_CHANNEL_ID);
client.subscribe(mqtt_subscribe_topic);
sprintf(mqtt_subscribe_topic, "channels/%lu/subscribe/fields/field2", CONTROL_CHANNEL_ID);
client.subscribe(mqtt_subscribe_topic);
Serial.println("Subscribed to all control topics");
// العودة لنمط العمل الطبيعي
blinkPattern = 4;
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// وميض سريع للإشارة لفشل الاتصال
for(int i = 0; i < 3; i++) {
digitalWrite(STATUS_LED_PIN, HIGH);
delay(100);
digitalWrite(STATUS_LED_PIN, LOW);
delay(100);
}
delay(5000);
}
}
}
// ==================== دالة إرسال البيانات إلى ThingSpeak ====================
void sendToThingSpeak() {
if (client.connected()) {
// بناء رسالة البيانات
String payload = "field1=" + String(temperature, 2) +
"&field2=" + String(humidity, 2) +
"&field3=" + String(fanStatus) +
"&field4=" + String(heaterStatus);
// إرسال البيانات إلى ThingSpeak
client.publish(mqtt_publish_topic, payload.c_str());
Serial.print("Data sent to ThingSpeak: ");
Serial.println(payload);
Serial.println("--------------------------------------");
}
}
void updateStatusLED() {
unsigned long currentMillis = millis();
if (currentMillis - lastBlink >= blinkInterval) {
lastBlink = currentMillis;
switch(blinkPattern) {
case 0: // اكتشاف الشبكة - وميض سريع جداً
statusLedState = !statusLedState;
digitalWrite(STATUS_LED_PIN, statusLedState);
break;
case 1: // نقطة وصول - وميض طويل
if (statusLedState == LOW) {
digitalWrite(STATUS_LED_PIN, HIGH);
statusLedState = HIGH;
} else {
digitalWrite(STATUS_LED_PIN, LOW);
statusLedState = LOW;
}
break;
case 2: // WiFi متصل - وميض متوسط
statusLedState = !statusLedState;
digitalWrite(STATUS_LED_PIN, statusLedState);
break;
case 3: // محاولة اتصال MQTT - وميض مزدوج
digitalWrite(STATUS_LED_PIN, HIGH);
delay(50);
digitalWrite(STATUS_LED_PIN, LOW);
delay(50);
digitalWrite(STATUS_LED_PIN, HIGH);
delay(50);
digitalWrite(STATUS_LED_PIN, LOW);
break;
case 4: // كل شيء يعمل - إضاءة ثابتة
digitalWrite(STATUS_LED_PIN, HIGH);
break;
default:
digitalWrite(STATUS_LED_PIN, LOW);
}
}
}
void setup() {
Serial.begin(115200);
// تهيئة المنافذ
pinMode(FAN_LED_PIN, OUTPUT);
pinMode(HEATER_LED_PIN, OUTPUT);
pinMode(STATUS_LED_PIN, OUTPUT); // LED المؤشر
digitalWrite(FAN_LED_PIN, LOW);
digitalWrite(HEATER_LED_PIN, LOW);
digitalWrite(STATUS_LED_PIN, LOW);
// بدء وميض LED للإشارة لبدء التشغيل
for(int i = 0; i < 5; i++) {
digitalWrite(STATUS_LED_PIN, HIGH);
delay(100);
digitalWrite(STATUS_LED_PIN, LOW);
delay(100);
}
// بدء مستشعر DHT
dht.begin();
// الاتصال بـ WiFi
setup_wifi();
// تهيئة MQTT
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
// إعداد مواضيع ThingSpeak
sprintf(mqtt_publish_topic, "channels/%lu/publish", SENSORS_CHANNEL_ID);
sprintf(mqtt_subscribe_topic, "channels/%lu/subscribe", CONTROL_CHANNEL_ID);
Serial.println("System started successfully with ThingSpeak integration!");
Serial.println("=======================================================");
}
void controlTemperature(float temp) {
if (temp > MAX_TEMP) {
int fanSpeed = map(temp, MAX_TEMP, MAX_TEMP + 5, 100, 255);
fanSpeed = constrain(fanSpeed, 100, 255);
analogWrite(FAN_LED_PIN, fanSpeed);
analogWrite(HEATER_LED_PIN, 0);
fanStatus = 1;
heaterStatus = 0;
Serial.print("Fan ON - Speed: ");
Serial.println(fanSpeed);
} else if (temp < MIN_TEMP) {
int heaterPower = map(temp, MIN_TEMP - 5, MIN_TEMP, 255, 100);
heaterPower = constrain(heaterPower, 100, 255);
analogWrite(HEATER_LED_PIN, heaterPower);
analogWrite(FAN_LED_PIN, 0);
heaterStatus = 1;
fanStatus = 0;
Serial.print("Heater ON - Power: ");
Serial.println(heaterPower);
} else {
Serial.println("Temperature ideal - Both OFF");
analogWrite(FAN_LED_PIN, 0);
analogWrite(HEATER_LED_PIN, 0);
fanStatus = 0;
heaterStatus = 0;
}
}
void loop() {
// تحديث حالة LED المؤشر
updateStatusLED();
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long now = millis();
// قراءة وإرسال البيانات كل 5 ثواني (لـ MQTT العادي)
if (now - lastMsg > interval) {
lastMsg = now;
// قراءة البيانات من المستشعر
temperature = dht.readTemperature();
humidity = dht.readHumidity();
// إذا فشلت القراءة، استخدام قيم افتراضية للتجربة
if (isnan(temperature) || isnan(humidity)) {
Serial.println("Failed to read from DHT sensor! Using default values.");
temperature = random(150, 300) / 10.0; // قيم بين 15 و30
humidity = random(300, 800) / 10.0; // قيم بين 30 و80
}
// عرض البيانات على Serial
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print("°C, Humidity: ");
Serial.print(humidity);
Serial.println("%");
// التحكم في درجة الحرارة
controlTemperature(temperature);
// إرسال البيانات عبر MQTT العادي
char tempString[8];
char humString[8];
dtostrf(temperature, 6, 2, tempString);
dtostrf(humidity, 6, 2, humString);
client.publish(mqtt_topic_temp, tempString);
client.publish(mqtt_topic_humidity, humString);
Serial.println("Data published to MQTT");
Serial.println("----------------------");
}
// إرسال البيانات إلى ThingSpeak كل 15 ثانية
if (now - lastThingSpeakUpdate > thingspeakInterval) {
lastThingSpeakUpdate = now;
sendToThingSpeak();
}
// تأخير بسيط للحفاظ على استقرار النظام
delay(100);
}