#include <WiFi.h>
#include <WebServer.h>
#include <Adafruit_NeoPixel.h>
#include <DHT.h> // Βιβλιοθήκη για DHT11
// ΣΤΟΙΧΕΙΑ Wi-Fi
const char* ssid = "Redmi";
const char* password = "12345678";
// Ορισμός Pins
#define BUTTON_1 12 // Touch button 1 (πάνω από LED 4)
#define BUTTON_2 13 // Touch button 2 (πάνω από LED 3)
#define BUTTON_3 14 // Touch button 3 (πάνω από LED 2)
#define RELAY_1 16 // Ρελέ 1
#define RELAY_2 17 // Ρελέ 2
#define LED_PIN 25 // LED strip
#define DHT_PIN 33 // DHT11 στο pin 33
#define NUM_LEDS 5
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
WebServer server(80);
// DHT11
#define DHTTYPE DHT11
DHT dht(DHT_PIN, DHTTYPE);
// Χρώματα (μόνο RGB)
uint32_t RED = strip.Color(255, 0, 0);
uint32_t GREEN = strip.Color(0, 255, 0);
uint32_t BLUE = strip.Color(0, 0, 255);
uint32_t OFF = strip.Color(0, 0, 0);
// Αντιστοίχηση buttons με LED
const int buttonToLed[3] = {4, 3, 2}; // BUTTON_1->LED4, BUTTON_2->LED3, BUTTON_3->LED2
const int buttonPins[3] = {BUTTON_1, BUTTON_2, BUTTON_3};
// Μεταβλητές για τις μετρήσεις
float temperature = 0.0;
float humidity = 0.0;
unsigned long lastRead = 0;
const unsigned long readInterval = 2000; // διάβασμα κάθε 2 δευτερόλεπτα
void checkButtons() {
static unsigned long lastPress = 0;
if (millis() - lastPress < 300) return;
for (int i = 0; i < 3; i++) {
if (digitalRead(buttonPins[i]) == LOW) {
strip.setPixelColor(buttonToLed[i], RED); // Προεπιλογή κόκκινο από τα buttons
strip.show();
lastPress = millis();
break;
}
}
}
void setLED(int index, uint32_t color) {
if (index >= 0 && index < NUM_LEDS) {
strip.setPixelColor(index, color);
strip.show();
}
}
void allLEDs(uint32_t color) {
for (int i = 0; i < NUM_LEDS; i++) strip.setPixelColor(i, color);
strip.show();
}
// Συνάρτηση για ανάγνωση DHT11 (καλείται περιοδικά)
void readDHT() {
if (millis() - lastRead >= readInterval) {
humidity = dht.readHumidity();
temperature = dht.readTemperature(); // σε °C
// Έλεγχος αν η ανάγνωση ήταν επιτυχής
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Αποτυχία ανάγνωσης DHT11");
humidity = -1;
temperature = -1;
}
lastRead = millis();
}
}
// Δημιουργία HTML σελίδας
String getHTML() {
String html = "<!DOCTYPE html><html>";
html += "<head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1'>";
html += "<style>";
html += "body { font-family: Arial; text-align: center; background: #ffe4e1; }"; // ροζ υπόβαθρο
html += ".container { max-width: 500px; margin: 20px auto; padding: 20px; background: #fff0f0; border-radius: 15px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }";
html += "button { padding: 12px 20px; font-size: 16px; margin: 5px; border: none; border-radius: 8px; cursor: pointer; width: 100px; }";
html += ".red { background: #e74c3c; color: white; } .green { background: #2ecc71; color: white; } .blue { background: #3498db; color: white; }";
html += ".on { background: #ff8c66; color: white; } .off { background: #ff6666; color: white; }"; // πορτοκαλί/ροζ
html += ".section { margin: 20px 0; padding: 15px; background: #ffe0e0; border-radius: 10px; }";
html += ".sensor { font-size: 24px; color: #b22222; }"; // σκούρο κόκκινο
html += ".sensor span { color: #ff4500; }"; // πορτοκαλί
html += "</style>";
html += "<script>";
html += "function fetchData() {";
html += " fetch('/data').then(response => response.json()).then(data => {";
html += " document.getElementById('temp').innerText = data.temp.toFixed(1);";
html += " document.getElementById('hum').innerText = data.hum.toFixed(1);";
html += " }).catch(err => console.log(err));";
html += "}";
html += "setInterval(fetchData, 2000);"; // ανανέωση κάθε 2 δευτερόλεπτα
html += "</script>";
html += "</head><body><div class='container'>";
html += "<h1 style='color:#b22222;'>ARD:Icon II Control</h1>";
// Ενότητα αισθητήρων
html += "<div class='section'><h3 style='color:#ff6347;'>🌡️ Θερμοκρασία & Υγρασία</h3>";
html += "<p class='sensor'>Θερμοκρασία: <span id='temp'>--</span> °C</p>";
html += "<p class='sensor'>Υγρασία: <span id='hum'>--</span> %</p>";
html += "</div>";
// Ρελέ
html += "<div class='section'><h3 style='color:#ff6347;'>🔌 Ρελέ</h3>";
html += "<a href='/relay1/on'><button class='on'>ΡΕΛΕ 1 ON</button></a>";
html += "<a href='/relay1/off'><button class='off'>ΡΕΛΕ 1 OFF</button></a><br>";
html += "<a href='/relay2/on'><button class='on'>ΡΕΛΕ 2 ON</button></a>";
html += "<a href='/relay2/off'><button class='off'>ΡΕΛΕ 2 OFF</button></a></div>";
// LED ανά θέση
html += "<div class='section'><h3 style='color:#ff6347;'>💡 LED ανά Θέση</h3>";
for (int i = 2; i <= 4; i++) {
html += "<div><b>LED " + String(i) + "</b><br>";
html += "<a href='/led" + String(i) + "/red'><button class='red'>R</button></a>";
html += "<a href='/led" + String(i) + "/green'><button class='green'>G</button></a>";
html += "<a href='/led" + String(i) + "/blue'><button class='blue'>B</button></a>";
html += "<a href='/led" + String(i) + "/off'><button class='off'>OFF</button></a></div>";
}
html += "</div>";
// Όλα τα LED
html += "<div class='section'><h3 style='color:#ff6347;'>✨ Όλα τα LED</h3>";
html += "<a href='/all/red'><button class='red'>ΟΛΑ R</button></a>";
html += "<a href='/all/green'><button class='green'>ΟΛΑ G</button></a>";
html += "<a href='/all/blue'><button class='blue'>ΟΛΑ B</button></a>";
html += "<a href='/all/off'><button class='off'>ΟΛΑ OFF</button></a></div>";
html += "</div></body></html>";
return html;
}
void setup() {
Serial.begin(115200);
// Pins
pinMode(RELAY_1, OUTPUT);
pinMode(RELAY_2, OUTPUT);
pinMode(BUTTON_1, INPUT_PULLUP);
pinMode(BUTTON_2, INPUT_PULLUP);
pinMode(BUTTON_3, INPUT_PULLUP);
digitalWrite(RELAY_1, LOW);
digitalWrite(RELAY_2, LOW);
// LED
strip.begin();
allLEDs(OFF);
// DHT11
dht.begin();
// Wi-Fi
Serial.print("Σύνδεση σε ");
Serial.println(ssid);
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 40) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\n✅ Συνδέθηκε! IP: " + WiFi.localIP().toString());
// Routes
server.on("/", []() { server.send(200, "text/html", getHTML()); });
// Διαδρομή για δεδομένα αισθητήρων (JSON)
server.on("/data", []() {
String json = "{\"temp\":" + String(temperature) + ",\"hum\":" + String(humidity) + "}";
server.send(200, "application/json", json);
});
// Relay 1
server.on("/relay1/on", []() { digitalWrite(RELAY_1, HIGH); server.sendHeader("Location", "/"); server.send(303); });
server.on("/relay1/off", []() { digitalWrite(RELAY_1, LOW); server.sendHeader("Location", "/"); server.send(303); });
// Relay 2
server.on("/relay2/on", []() { digitalWrite(RELAY_2, HIGH); server.sendHeader("Location", "/"); server.send(303); });
server.on("/relay2/off", []() { digitalWrite(RELAY_2, LOW); server.sendHeader("Location", "/"); server.send(303); });
// LED routes
for (int led = 2; led <= 4; led++) {
int idx = led;
server.on(("/led" + String(led) + "/red").c_str(), [idx]() { setLED(idx, RED); server.sendHeader("Location", "/"); server.send(303); });
server.on(("/led" + String(led) + "/green").c_str(), [idx]() { setLED(idx, GREEN); server.sendHeader("Location", "/"); server.send(303); });
server.on(("/led" + String(led) + "/blue").c_str(), [idx]() { setLED(idx, BLUE); server.sendHeader("Location", "/"); server.send(303); });
server.on(("/led" + String(led) + "/off").c_str(), [idx]() { setLED(idx, OFF); server.sendHeader("Location", "/"); server.send(303); });
}
// All LEDs
server.on("/all/red", []() { allLEDs(RED); server.sendHeader("Location", "/"); server.send(303); });
server.on("/all/green", []() { allLEDs(GREEN); server.sendHeader("Location", "/"); server.send(303); });
server.on("/all/blue", []() { allLEDs(BLUE); server.sendHeader("Location", "/"); server.send(303); });
server.on("/all/off", []() { allLEDs(OFF); server.sendHeader("Location", "/"); server.send(303); });
server.begin();
} else {
Serial.println("\n❌ Αποτυχία σύνδεσης!");
}
}
void loop() {
server.handleClient();
checkButtons();
readDHT(); // περιοδική ανάγνωση αισθητήρα
}