Spirulino v1.21 NodeMCU

/*****
 
 
   _____       _            _ _              
  / ____|     (_)          | (_)             
 | (___  _ __  _ _ __ _   _| |_ _ __   ___   
  \___ \| '_ \| | '__| | | | | | '_ \ / _ \  
  ____) | |_) | | |  | |_| | | | | | | (_) | 
 |_____/| .__/|_|_|   \__,_|_|_|_| |_|\___/  
        | |                                  
        |_|                                  

 v 1.21 4-8-2021

 Emilio Roscini
 
*****/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <PubSubClient.h>
#include "DHT.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;          
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);
// Temperature value
float temp;

// Uncomment one of the lines bellow for whatever DHT sensor type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

// Change the credentials below, so your ESP8266 connects to your router
const char* ssid = "ami";
const char* password = "chokurei";

// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
const char* mqtt_server = "192.168.2.100";

// Initializes the espClient. You should change the espClient name if you have multiple ESPs running in your home automation system
WiFiClient espClient;
PubSubClient client(espClient);

// DHT Sensor - GPIO 5 = D1 on ESP-12E NodeMCU board
const int DHTPin = 5;

// Lamp - LED - GPIO 4 = D2 on ESP-12E NodeMCU board
const int pump = 12;
const int espled1 = 16;
const int espled2 = 2;
const int rele2 = 13;
const int rele3 = 14;

// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);

// Variables timers
int aCceso = 0;
int sPento = 0;
int naCceso = 0;
int nsPento = 0;
int tEmpo = 60000;
int fLush = 5000;

// Timers auxiliar variables
long now = millis();
long Measure = 0;
long lastMeasure = 0;
long ultimaMeasure = 0;
long lampo = 0;
long lampino = 0;

// Variables pump
char* pOmpa = "Spenta";
int Pompa = 0;
int sTato = 0;
int vrele2 = 0;
int vrele3 = 0;

// Variables light
char* cIelo = "Notte";
int cOndizione = 0;
float voltage;

bool pIng = LOW;
bool tras = LOW;

// Don't change the function below. This functions connects your ESP8266 to your router
void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
}

// This functions is executed when some device publishes a message to a topic that your ESP8266 is subscribed to
// Change the function below to add logic to your program, so when a device publishes a message to a topic that 
// your ESP8266 is subscribed you can actually do something
void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;

  
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();
  
  lampino = millis();
  digitalWrite(espled2, LOW);
  tras = LOW;

   // Convert on off mqtt command to boolean variable
   if(topic=="room/pump"){
      Serial.print("La pompa é ");
      if(messageTemp == "on"){
        EEPROM.put(10, 1);
        EEPROM.commit();
        sTato = 1;
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        EEPROM.put(10, 0);
        EEPROM.commit();
        sTato = 0;
        Serial.print("Off");
      }
  }


     if(topic=="room/rele2"){
      if(messageTemp == "on"){
        EEPROM.put(2, 1);
        EEPROM.commit();
        vrele2 = 1;
      }
      else if(messageTemp == "off"){
        EEPROM.put(2, 0);
        EEPROM.commit();
        vrele2 = 0;
      }
  }

     if(topic=="room/rele3"){
      if(messageTemp == "on"){
        EEPROM.put(6, 1);
        EEPROM.commit();
        vrele3 = 1;
      }
      else if(messageTemp == "off"){
        EEPROM.put(6, 0);
        EEPROM.commit();
        vrele3 = 0;
      }
  }
  

    // Convert mqtt slide value to integer
    if(topic=="room/timeron"){
      aCceso = messageTemp.toInt();
      EEPROM.put(14, aCceso);
      EEPROM.commit();
      Serial.print(aCceso);

  }
    if(topic=="room/timeroff"){
      sPento = messageTemp.toInt();
      EEPROM.put(18, sPento);
      EEPROM.commit();
      Serial.print(sPento);

  }

    if(topic=="room/ntimeron"){
      naCceso = messageTemp.toInt();
      EEPROM.put(22, naCceso);
      EEPROM.commit();
      Serial.print(naCceso);

  }
    if(topic=="room/ntimeroff"){
      nsPento = messageTemp.toInt();
      EEPROM.put(26, nsPento);
      EEPROM.commit();
      Serial.print(nsPento);

  }

   // Convert mqtt light level slide to integer
   if(topic=="room/condizione"){
     cOndizione = messageTemp.toInt();
     EEPROM.put(30, cOndizione);
     EEPROM.commit();
   Serial.print(cOndizione);

  }
  
  Serial.println();
}

// This functions reconnects your ESP8266 to your MQTT broker
// Change the function below if you want to subscribe to more topics with your ESP8266 
void reconnect() {
  // Loop until we're reconnected
  if (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    /*
     YOU MIGHT NEED TO CHANGE THIS LINE, IF YOU'RE HAVING PROBLEMS WITH MQTT MULTIPLE CONNECTIONS
     To change the ESP device ID, you will have to give a new name to the ESP8266.
     Here's how it looks:
       if (client.connect("ESP8266Client")) {
     You can do it like this:
       if (client.connect("ESP1_Office")) {
     Then, for the other ESP:
       if (client.connect("ESP2_Garage")) {
      That should solve your MQTT multiple connections problem
    */
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      digitalWrite(espled1, LOW);  
      // Subscribe or resubscribe to a topic
      client.subscribe("room/pump");
      client.subscribe("room/rele2");
      client.subscribe("room/rele3");
      client.subscribe("room/timeron");
      client.subscribe("room/timeroff");
      client.subscribe("room/ntimeron");
      client.subscribe("room/ntimeroff");
      client.subscribe("room/condizione");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
    }
  }
}

// The setup function sets your ESP GPIOs to Outputs, starts the serial communication at a baud rate of 115200
// Sets your mqtt broker and sets the callback function
// The callback function is what receives messages and actually controls the outputs

/////////////////////////////////////////////////////////

void setup() {
  sensors.begin();
  EEPROM.begin(256);
  pinMode(pump, OUTPUT);
  pinMode(rele2, OUTPUT);
  pinMode(rele3, OUTPUT);
  pinMode(espled1, OUTPUT);
  pinMode(espled2, OUTPUT);

  digitalWrite(espled1, HIGH);
  digitalWrite(espled2, HIGH);
  
  dht.begin();
  
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  //////////////////////////////////////
  //      OTA setup
  //////////////////////////////////////

    // Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  // ArduinoOTA.setHostname("myesp8266");

  // No authentication by default
  // ArduinoOTA.setPassword((const char *)"123");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("OTA Ready");
 

///////////////////////////////////////////////////

      vrele3 = EEPROM.read(6);
    if (vrele3 == 1){
       digitalWrite(rele3,HIGH);
    }
    if (vrele3 == 0){
       digitalWrite(rele3,LOW);
    }    
    
    vrele2 = EEPROM.read(2);
    if (vrele2 == 1){
       digitalWrite(rele2,HIGH);
    }
    if (vrele2 == 0){
       digitalWrite(rele2,LOW);
    }



    sTato = EEPROM.read(10);
    aCceso = EEPROM.read(14);
    sPento = EEPROM.read(18);
    naCceso = EEPROM.read(22);
    nsPento = EEPROM.read(26);
    cOndizione = EEPROM.read(30);
    

}


////////////////////////////////////////////////////////////

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  if(!client.loop())
    client.connect("ESP8266Client");

    ArduinoOTA.handle();

    vrele3 = EEPROM.read(6);
    if (vrele3 == 1){
       digitalWrite(rele3,HIGH);
    }
    if (vrele3 == 0){
      digitalWrite(rele3,LOW);
         if (Pompa == 1) {
         digitalWrite(rele3,HIGH);
         }
      }    
    
    vrele2 = EEPROM.read(2);
    if (vrele2 == 1){
       digitalWrite(rele2,HIGH);
    }
    if (vrele2 == 0){
       digitalWrite(rele2,LOW);
    }

  now = millis();

     if (tras == HIGH){
      if (millis() - lampino > 300) {
        pIng = LOW;
        digitalWrite(espled2,HIGH);  
      }
     }

       if (pIng == HIGH){
      if (millis() - lampo > 1000) {
        pIng = LOW;
        digitalWrite(espled2,HIGH);  
      }
     }
    
  // Night an day timers
    sTato = EEPROM.read(10);
    aCceso = EEPROM.read(14);
    sPento = EEPROM.read(18);
    naCceso = EEPROM.read(22);
    nsPento = EEPROM.read(26);

      
      if (sTato == 1){
        if (cIelo == "Giorno") {
         if ((millis() - ultimaMeasure) > (sPento*tEmpo)){
          digitalWrite(pump,HIGH);
          pOmpa = "Accesa";
          Pompa = 1;
            if ((millis() - ultimaMeasure - (sPento*tEmpo)) > (aCceso*tEmpo)) {
              ultimaMeasure = millis();
              digitalWrite(pump,LOW);
              pOmpa = "Spenta";
              Pompa = 0;
            }
           }
         }
      

        if (cIelo == "Notte") {
         if ((millis() - Measure) > (nsPento*tEmpo)){
          digitalWrite(pump,HIGH);
          pOmpa = "Accesa";
          Pompa = 1;
            if ((millis() - Measure - (nsPento*tEmpo)) > (naCceso*tEmpo)) {
              Measure = millis();
              digitalWrite(pump,LOW);
              pOmpa = "Spenta";
              Pompa = 0; 
            }
           }
         }
      }

  // Publishes new temperature and humidity 
  if (now - lastMeasure > fLush) {
    lastMeasure = now;
    pIng = HIGH;
    lampo = millis();
    digitalWrite(espled2,LOW);
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    float h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    float t = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    float f = dht.readTemperature(true);

   // Read light level and decide if its night or day

   int sensorValue = analogRead(A0);   // read the input on analog pin 0

   float voltage = sensorValue * (100.0 / 1023.0);   // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V)

    cOndizione = EEPROM.read(30);
    if (voltage >= cOndizione) {
      cIelo = "Giorno";
    }
    if (voltage < cOndizione) {
      cIelo = "Notte";
    }
    
    // Computes temperature values in Celsius
    float hic = dht.computeHeatIndex(t, h, false);
    static char temperatureTemp[7];
    dtostrf(hic, 6, 2, temperatureTemp);
    
    // Uncomment to compute temperature values in Fahrenheit 
    // float hif = dht.computeHeatIndex(f, h);
    // static char temperatureTemp[7];
    // dtostrf(hif, 6, 2, temperatureTemp);
    
    static char humidityTemp[7];
    dtostrf(h, 6, 2, humidityTemp);

    // New temperature readings
    sensors.requestTemperatures(); 
    // Temperature in Celsius degrees
    temp = sensors.getTempCByIndex(0);

    // Convert integer to string
    static char inTemp[7];
    dtostrf(temp, 6, 2, inTemp);

    static char diLux[7];
    dtostrf(voltage, 6, 2, diLux);

    static char poMpin[7];
    dtostrf(Pompa, 6, 2, poMpin);

    static char ACceso[7];
    dtostrf(aCceso, 6, 2, ACceso);

    static char SPento[7];
    dtostrf(sPento, 6, 2, SPento);

    static char NACceso[7];
    dtostrf(naCceso, 6, 2, NACceso);

    static char NSPento[7];
    dtostrf(nsPento, 6, 2, NSPento);

    static char COndizione[7];
    dtostrf(cOndizione, 6, 2, COndizione);

    // Publishes values
    client.publish("room/temperature", temperatureTemp);
    client.publish("room/humidity", humidityTemp);
    client.publish("room/intemp", inTemp);
    client.publish("room/lux", diLux);
    client.publish("room/stato", pOmpa);
    client.publish("room/cielo", cIelo);
    client.publish("room/pompa", poMpin);

    if (vrele2 == 1){
      client.publish("room/ferele2", "on");
    }
    if (vrele2 == 0){
      client.publish("room/ferele2", "off");
    }

    if (vrele3 == 1){
      client.publish("room/ferele3", "on");
    }
    if (vrele3 == 0){
      client.publish("room/ferele3", "off");
    }

    if (sTato == 1){
      client.publish("room/festato", "on");
    }
    if (sTato == 0){
      client.publish("room/festato", "off");
    }

    client.publish("room/feacceso", ACceso);
    client.publish("room/fespento", SPento);
    client.publish("room/fenacceso", NACceso);
    client.publish("room/fenspento", NSPento);
    client.publish("room/fecondizione", COndizione);
        
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t Temperature: ");
    Serial.print(t);
    Serial.print(" *C ");
    Serial.print(f);
    Serial.print(" *F\t Heat index: ");
    Serial.print(hic);
    Serial.print(" *C ");
    Serial.print(temp);
    Serial.print(" *C in");
    Serial.print(" Luminositá:");
    Serial.print(voltage);
    Serial.print(" la pompa é ");
    Serial.print(pOmpa);
    Serial.print(" é di ");
    Serial.println(cIelo);
    Serial.println(ACceso);
    Serial.println(aCceso);
  }
}