#include <ESP8266WiFi.h>

#include <ESP8266WebServer.h>

#include <IRremoteESP8266.h>

#include <IRrecv.h>

#include <IRutils.h>

#include <DHT.h> // Include DHT sensor library

// Wi-Fi credentials

const char* ssid = “Alien_2.4Ghz”;

const char* password = “tenda_gepon”;

// Create a web server on port 80

ESP8266WebServer server(80);

// Define GPIO pins for Relays and Switches

#define RelayPin1 D3  // GPIO5

#define RelayPin2 D3  // GPIO4

#define RelayPin3 D3  // GPIO0

#define RelayPin4 D4  // GPIO2

#define IR_RECEIVE_PIN D5 // GPIO16

// Define DHT11 type and pin

#define DHTPIN D6         // GPIO12

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE); // Create DHT object

// Relay states

bool toggleState_1 = LOW;

bool toggleState_2 = LOW;

bool toggleState_3 = LOW;

bool toggleState_4 = LOW;

// Update HEX codes of IR Remote buttons

#define IR_Button_1  0x1FE50AF

#define IR_Button_2  0x1FED827

#define IR_Button_3  0x1FEF807

#define IR_Button_4  0x1FE30CF

#define IR_All_On    0x1FE48B7

#define IR_All_Off   0x1FE58A7

// IR Receiver

IRrecv irrecv(IR_RECEIVE_PIN);

decode_results results;

void setup() {

  Serial.begin(115200);

  // Initialize Wi-Fi

  WiFi.begin(ssid, password);

  Serial.print(“Connecting to Wi-Fi”);

  while (WiFi.status() != WL_CONNECTED) {

    delay(1000);

    Serial.print(“.”);

  }

  Serial.println(“\nConnected to Wi-Fi!”);

  Serial.print(“IP Address: “);

  Serial.println(WiFi.localIP());

  // Initialize DHT sensor

  dht.begin();

  // Initialize web server routes

  server.on(“/toggle”, handleToggle);

   server.on(“/”, HTTP_GET, handleRoot);   // Relay control page

  server.on(“/toggle”, HTTP_GET, handleToggle);  // Relay toggle

  server.on(“/temperature”, HTTP_GET, handleTemperature);  // Temperature and humidity data

  server.begin();

  Serial.println(“Web server started!”);

  // Initialize Relays as output and set them OFF

  pinMode(RelayPin1, OUTPUT);

  pinMode(RelayPin2, OUTPUT);

  pinMode(RelayPin3, OUTPUT);

  pinMode(RelayPin4, OUTPUT);

  digitalWrite(RelayPin1, HIGH);

  digitalWrite(RelayPin2, HIGH);

  digitalWrite(RelayPin3, HIGH);

  digitalWrite(RelayPin4, HIGH);

  // Start IR receiver

  irrecv.enableIRIn();

  Serial.println(“System initialized”);

}

void loop() {

  // Handle client requests for the web server

  server.handleClient();

  // Handle IR commands

  if (irrecv.decode(&results)) {

    handleIRCommand(results.value);

    irrecv.resume(); // Receive the next value

  }

}

void handleIRCommand(uint32_t value) {

  switch (value) {

    case IR_Button_1:

      toggleRelay(1);

      break;

    case IR_Button_2:

      toggleRelay(2);

      break;

    case IR_Button_3:

      toggleRelay(3);

      break;

    case IR_Button_4:

      toggleRelay(4);

      break;

    case IR_All_On:

      setAllRelays(true);

      break;

    case IR_All_Off:

      setAllRelays(false);

      break;

    default:

      Serial.println(“Unknown IR code”);

  }

}

void toggleRelay(int relay) {

  switch (relay) {

    case 1:

      toggleState_1 = !toggleState_1;

      digitalWrite(RelayPin1, toggleState_1 ? LOW : HIGH);

      Serial.println(toggleState_1 ? “Relay 1 ON” : “Relay 1 OFF”);

      break;

    case 2:

      toggleState_2 = !toggleState_2;

      digitalWrite(RelayPin2, toggleState_2 ? LOW : HIGH);

      Serial.println(toggleState_2 ? “Relay 2 ON” : “Relay 2 OFF”);

      break;

    case 3:

      toggleState_3 = !toggleState_3;

      digitalWrite(RelayPin3, toggleState_3 ? LOW : HIGH);

      Serial.println(toggleState_3 ? “Relay 3 ON” : “Relay 3 OFF”);

      break;

    case 4:

      toggleState_4 = !toggleState_4;

      digitalWrite(RelayPin4, toggleState_4 ? LOW : HIGH);

      Serial.println(toggleState_4 ? “Relay 4 ON” : “Relay 4 OFF”);

      break;

  }

}

void setAllRelays(bool state) {

  toggleState_1 = state;

  toggleState_2 = state;

  toggleState_3 = state;

  toggleState_4 = state;

  digitalWrite(RelayPin1, state ? LOW : HIGH);

  digitalWrite(RelayPin2, state ? LOW : HIGH);

  digitalWrite(RelayPin3, state ? LOW : HIGH);

  digitalWrite(RelayPin4, state ? LOW : HIGH);

  Serial.println(state ? “All Relays ON” : “All Relays OFF”);

}

void readDHTSensor(String &response) {

  float humidity = dht.readHumidity();

  float temperature = dht.readTemperature();

  // Check if readings are valid

  if (isnan(humidity) || isnan(temperature)) {

    response += “Failed to read from DHT sensor!”;

    return;

  }

  // Append readings to the response

  response += “Temperature: ” + String(temperature) + “°C<br>”;

  response += “Humidity: ” + String(humidity) + “%<br>”;

}

// Web server root handler

void handleRoot() {

  // Read temperature and humidity

  float temperature = dht.readTemperature(); // Get temperature in Celsius

  float humidity = dht.readHumidity(); // Get humidity percentage

  // Check if the readings are valid

  if (isnan(temperature) || isnan(humidity)) {

    temperature = 0;

    humidity = 0;

  }

  String html = R”rawliteral(

    <!DOCTYPE html>

    <html>

    <head>

      <title>Relay Control</title>

      <style>

        @import url(‘https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css’);

        body {

          font-family: Arial, sans-serif;

          text-align: center;

          padding: 20px;

        }

        .relay-container {

          margin: 20px;

        }

        .relay-label {

          font-size: 20px;

          margin-right: 10px;

        }

        .toggle-button {

          width: 60px;

          height: 60px;

          cursor: pointer;

          border: none;

          border-radius: 30px;

          background-color: #ddd;

          display: flex;

          justify-content: center;

          align-items: center;

          font-size: 24px;

          color: black;

        }

        .toggle-on {

          background-color: #4caf50;

          color: white;

        }

        .toggle-off {

          background-color: #f44336;

          color: white;

        }

        .sensor-data {

          font-size: 24px;

          margin-top: 20px;

        }

      </style>

    </head>

    <body>

       <div class=”sensor-data”>

        <h2 id=”temperature”><i class=”fa fa-temperature-high”></i> : %.2f &deg;C</h2>

        <h2 id=”humidity”><i class=”fas fa-cloud-rain”></i> : %.2f %</h2>

      </div>

       <div id=”relays”>

        <!– Relay Controls –>

      </div>

      <script>

        const relayCount = 4; // Number of relays

        const relayContainer = document.getElementById(“relays”);

        for (let i = 1; i <= relayCount; i++) {

          const container = document.createElement(“div”);

          container.classList.add(“relay-container”);

          const label = document.createElement(“span”);

          label.classList.add(“relay-label”);

          label.innerText = `Relay ${i}`;

          const button = document.createElement(“button”);

          button.classList.add(“toggle-button”, “toggle-off”);

          button.innerHTML = ‘<i class=”fas fa-power-off”></i>’;

          button.onclick = () => toggleRelay(i, button);

          container.appendChild(label);

          container.appendChild(button);

          relayContainer.appendChild(container);

        }

        function toggleRelay(relay, button) {

          const xhr = new XMLHttpRequest();

          xhr.open(“GET”, `/toggle?relay=${relay}`, true);

          xhr.onload = () => {

            if (xhr.status === 200) {

              const isOn = button.classList.contains(“toggle-off”);

              button.innerHTML = isOn

                ? ‘<i class=”fas fa-toggle-on”></i>’

                : ‘<i class=”fas fa-toggle-off”></i>’;

              button.classList.toggle(“toggle-on”);

              button.classList.toggle(“toggle-off”);

            }

          };

          xhr.send();

        }

        // Fetch and update the temperature and humidity every 5 seconds

        setInterval(() => {

          fetch(‘/temperature’)

            .then(response => response.json())

            .then(data => {

              document.getElementById(‘temperature’).innerHTML = `<i class=”fa fa-temperature-high”></i>  ${data.temperature} &deg;C`;

              document.getElementById(‘humidity’).innerHTML = `<i class=”fas fa-cloud-rain”></i> ${data.humidity} %`;

            });

        }, 5000);  // Update every 5 seconds

      </script>

    </body>

    </html>

  )rawliteral”;

  // Replace placeholders with actual values

  html.replace(“%.2f”, String(temperature).c_str());

  html.replace(“%.2f”, String(humidity).c_str());

  server.send(200, “text/html”, html);

}

void handleTemperature() {

  // Read temperature and humidity

  float temperature = dht.readTemperature(); // Get temperature in Celsius

  float humidity = dht.readHumidity(); // Get humidity percentage

  // Check if the readings are valid

  if (isnan(temperature) || isnan(humidity)) {

    temperature = 0;

    humidity = 0;

  }

  // Return the temperature and humidity as JSON

  String jsonResponse = “{“;

  jsonResponse += “\”temperature\”: ” + String(temperature) + “,”;

  jsonResponse += “\”humidity\”: ” + String(humidity);

  jsonResponse += “}”;

  server.send(200, “application/json”, jsonResponse);

}

// Web server toggle handler

void handleToggle() {

  String relay = server.arg(“relay”); // Get the relay number from the URL

  if (relay == “1”) {

    toggleRelay(1);

  } else if (relay == “2”) {

    toggleRelay(2);

  } else if (relay == “3”) {

    toggleRelay(3);

  } else if (relay == “4”) {

    toggleRelay(4);

  } else {

    server.send(400, “text/plain”, “Invalid relay number!”);

    return;

  }

  server.send(200, “text/plain”, “Relay toggled!”);

}