Spirulino v1.0 – NodeMCU

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

 v 1.0 2-8-2021

 Emilio Roscini
 
*****/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#include <OneWire.h>
#include <DallasTemperature.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.43.24";

// 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 = 16;

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

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

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

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

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

// 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();

   // Convert on off mqtt command to boolean variable
   if(topic=="room/pump"){
      Serial.print("La pompa é ");
      if(messageTemp == "on"){
        sTato = HIGH;
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        sTato = LOW;
        Serial.print("Off");
      }
  }

    // Convert mqtt slide value to integer
    if(topic=="room/timeron"){
      aCceso = (messageTemp.toInt())*tEmpo;
      Serial.print(aCceso);

  }
    if(topic=="room/timeroff"){
      sPento = (messageTemp.toInt())*tEmpo;
      Serial.print(sPento);

  }

    if(topic=="room/ntimeron"){
      naCceso = (messageTemp.toInt())*tEmpo;
      Serial.print(naCceso);

  }
    if(topic=="room/ntimeroff"){
      nsPento = (messageTemp.toInt())*tEmpo;
      Serial.print(nsPento);

  }

   // Convert mqtt light level slide to integer
   if(topic=="room/condizione"){
   cOndizione = messageTemp.toInt();
   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
  while (!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");  
      // Subscribe or resubscribe to a topic
      client.subscribe("room/pump");
      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());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

// 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();
  pinMode(pump, OUTPUT);
  
  dht.begin();
  
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

}

// For this project, you don't need to change anything in the loop function. Basically it ensures that you ESP is connected to your broker
void loop() {

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

  now = millis();
    
  // Night an day timers

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

        if (cIelo == "Notte") {
         if ((millis() - ultimaMeasure) > nsPento){
          digitalWrite(pump,LOW);
          pOmpa = "Accesa";
            if ((millis() - ultimaMeasure -nsPento) > naCceso) {
              ultimaMeasure = millis();
              digitalWrite(pump,HIGH);
              pOmpa = "Spenta"; 
            }
           }
         }
      }

  // Publishes new temperature and humidity every 30 seconds
  if (now - lastMeasure > 30000) {
    lastMeasure = now;
    // 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);

    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }

   // 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)


    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);

    // 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);
        
    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.println(pOmpa);
    Serial.print(" é di ");
    Serial.print(cIelo);
  }
}