//ESP8266 IoT 5-relay control
//with DHT11 module for humidity and temperature Readings
//By EasyElectronics - puneet maheshwari
//The pieces of code are taken from multiple sources and combined
//For using in different rooms need to change the room number - roomX
#include <Arduino.h>
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include "DHTesp.h"

DHTesp dht; // initialising the DHT library and providing object

//EDIT THESE LINES TO MATCH YOUR SETUP
#define MQTT_SERVER “xxx.xxx.xxx.xxx”. //enter your MQTT server IP address
const char* ssid = “SSID name”; // wifi name
const char* password = “WIFI Password“; //wifi password
 
//define Pins for relay on ESP8266

const int lightPin1 = 14; // D5 Pin
const int lightPin2 = 5; // D1 Pin
const int lightPin3 = 4; // D2 Pin
const int lightPin4 = 0; // D3 Pin
const int lightPin5 = 2; // D4 Pin

//MQTT assignment of topics
char* lightTopic1 = "room1/light1";
char* lightTopic2 = "room1/light2";
char* lightTopic3 = "room1/light3";
char* lightTopic4 = "room1/light4";
char* lightTopic5 = "room1/light5";
char* humidity = "room1/humidity";
char* temperature = "room1/temp";

int period = 6000; //delay of 6 seconds for DHT data
unsigned long time_now = 0;

 void callback(char* topic, byte* payload, unsigned int length);

 WiFiClient wifiClient;

 PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);

void setup() {
  //initialize the light as an output and set to LOW (off)
  pinMode(lightPin1, OUTPUT);
  digitalWrite(lightPin1, LOW);
  pinMode(lightPin2, OUTPUT);
  digitalWrite(lightPin2, LOW);
  pinMode(lightPin3, OUTPUT);
  digitalWrite(lightPin3, LOW);
  pinMode(lightPin4, OUTPUT);
  digitalWrite(lightPin4, LOW);
  pinMode(lightPin5, OUTPUT);
  digitalWrite(lightPin5, LOW);

dht.setup(12, DHTesp::DHT11); // Connect DHT sensor to GPIO 12 (D6 pin)
  //start the serial line for debugging
  Serial.begin(115200);
  delay(100);

  void reconnect();
  //start wifi subsystem
  WiFi.begin(ssid, password);
  //attempt to connect to the WIFI network and then connect to the MQTT server
  reconnect();
  //wait a bit before starting the main loop
  delay(2000);
}

void loop() {
  void reconnect();
  //reconnect if connection is lost
  if (!client.connected() && WiFi.status() == 3) {
    reconnect();
  }

  //maintain MQTT connection
  client.loop();

  //MUST delay to allow ESP8266 WIFI functions to run
 delay(10);

// start DHT11 Readings and publish to the MQQT server and then delay for 60 secs
  if (millis() > time_now + period){
    time_now = millis();
    float humidity = dht.getHumidity();
    float temperature = dht.getTemperature();
    Serial.println(dht.getStatusString());
    Serial.print("\t");
    Serial.print(humidity, 1);
    Serial.print("\t\t");
    Serial.print(temperature, 1);
    Serial.println("\t\t");
    client.publish("room1/temp", String(temperature).c_str(), true);
    client.publish("room1/humidity", String(humidity).c_str(), true);
  }
}

void callback(char* topic, byte* payload, unsigned int length) {

  // light 1
  if (strcmp(topic, "room1/light1") == 0) {
    //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message
    if (payload[0] == '1') {
      digitalWrite(lightPin1, HIGH);
      client.publish("room1/light1", "Light On");
      Serial.println("Light1 on");
    }
    //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message
    else if (payload[0] == '0') {
      digitalWrite(lightPin1, LOW);
      client.publish("room1/light1", "Light Off");
      Serial.println("Light1 off");

    }
  }
  //light 2
  if (strcmp(topic, "room1/light2") == 0) {
    //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message
    if (payload[0] == '1') {
      digitalWrite(lightPin2, HIGH);
      client.publish("room1/light2", "Light On");
      Serial.println("Light2 on");

    }
    //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message
    else if (payload[0] == '0') {
      digitalWrite(lightPin2, LOW);
      client.publish("room1/light2", "Light Off");
      Serial.println("Light2 off");

    }
  }
  //light 3
  if (strcmp(topic, "room1/light3") == 0) {
    //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message
    if (payload[0] == '1') {
      digitalWrite(lightPin3, HIGH);
      client.publish("room1/light3", "Light On");
      Serial.println("Light3 on");

    }
    //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message
    else if (payload[0] == '0') {
      digitalWrite(lightPin3, LOW);
      client.publish("room1/light3", "Light Off");
      Serial.println("Light3 off");

    }
  }
  //light 4
  if (strcmp(topic, "room1/light4") == 0) {
    //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message
    if (payload[0] == '1') {
      digitalWrite(lightPin4, HIGH);
      client.publish("room1/light4", "Light On");
      Serial.println("Light4 on");

    }
    //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message
    else if (payload[0] == '0') {
      digitalWrite(lightPin4, LOW);
      client.publish("room1/light4", "Light Off");
      Serial.println("Light4 off");

    }
  }
  //light 5
  if (strcmp(topic, "room1/light5") == 0) {
    //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message
    if (payload[0] == '1') {
      digitalWrite(lightPin5, HIGH);
      client.publish("room1/light5", "Light On");
      Serial.println("Light5 on");

    }
    //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message
    else if (payload[0] == '0') {
      digitalWrite(lightPin5, LOW);
      client.publish("room1/light5", "Light Off");
      Serial.println("Light5 off");

    }
  }
}

  //generate unique name from MAC addr for ESP8266
String macToStr(const uint8_t* mac) {

  String result;

  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);

    if (i < 5) {
      result += ':';
    }
  }

  return result;
}

  void reconnect() {
    //attempt to connect to the wifi if connection is lost
    if (WiFi.status() != WL_CONNECTED) {
      //debug printing
      Serial.print("Connecting to ");
      Serial.println(ssid);
      //loop while we wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      //print out some more debug once connected
      Serial.println("");
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
    }
    //make sure we are connected to WIFI before attemping to reconnect to MQTT
    if (WiFi.status() == WL_CONNECTED) {
      // Loop until we're reconnected to the MQTT server
      while (!client.connected()) {
        Serial.print("Attempting MQTT connection...");

        // Generate client name based on MAC address and last 8 bits of microsecond counter
        String clientName;
        clientName += "esp8266-";
        uint8_t mac[6];
        WiFi.macAddress(mac);
        clientName += macToStr(mac);

      //if connected, subscribe to the topic(s) we want to be notified about
      if (client.connect((char*) clientName.c_str())) {
        Serial.print("\tMQTT Connected");
        Serial.print("\nMAC address : "+ clientName);
        client.subscribe(lightTopic1);
        client.subscribe(lightTopic2);
        client.subscribe(lightTopic3);
        client.subscribe(lightTopic4);
        client.subscribe(lightTopic5);

      }
      //otherwise print failed for debugging
      else {
        Serial.println("\tFailed.");
        abort();
      }
    }
  }
  }