#include <NTPClient.h> //libreria necessaria per ottenere data e ora da un Server NTP
#include <WiFiUdp.h> //libreria per utilizzare il protocollo UDP sulla porta 123 del Server NTP
#include <ESP8266WebServer.h>
#include <DHT.h> //libreria necessaria per utilizzare il sensore DHT11
#define sensorePin D1 // pin di ESP8266 NodeMCU collegato all'uscita (pin OUT) del sensore DHT1
#define tipoDHT DHT11
/* definisce il tipo di sensore della famiglia DHT: in questo caso viene selezionato DHT11
* ma esistono sono altri sensori quali DHT21 e DHT22
*/
DHT dht(sensorePin,tipoDHT); //Istanzia l'oggetto dht della classe DHT
// Configurazione WiFI: impostazione delle credenziali di rete
const char* ssid = "XXXXXXXX"; //Inserire qui l'SSID
const char* password = "yyyyyyyy"; //Inserire qui la password WiFi
/* Configurazione IP statico/fisso della scheda ESP8266. Occorre utilizzare un indirizzo IP disponibile
* nella rete locale, il gateway corrispondente e la subnet mask
* Qui, ad esempio ho utilizzato l'IP 192.168.1.200
*/
IPAddress IP_ESP8266(192, 168, 1, 200);
IPAddress IP_gateway(192, 168, 1, 1);
IPAddress subnet_mask(255, 255, 0, 0);
//
ESP8266WebServer server(80);
/* Dichiara l'oggetto server della libreria ESP8266WebServer. Il costruttore di questo oggetto prende come
* parametro la porta 80 (predefinita per HTTP) dove il server si pone in ascolto
*/
WiFiUDP ntpUDP; //Istanzia l'oggetto ntpUDP della classe WiFiUDP
NTPClient timeClient(ntpUDP, "pool.ntp.org");// Definisce l'oggetto timeClient per recuperare data e ora dal Server NTP
float t; //temperatura
float h; //umidità
String dataora; //data e ora della misura del sensore
//Array dei mesi per scrivere la data nel formato gg mese aa es 7 maggio 2021
String mesi[12]={"gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"};
//
//
void setup()
{
// apre una connessione seriale. A scopo di debug inviamo alcuni messaggi al monitor seriale
pinMode(sensorePin, INPUT);
dht.begin(); //inizializza l'oggetto dht
Serial.begin(115200);
delay(1000);
Serial.println(ssid);
//con il metodo WiFi.config() configura la scheda ESP8266 conl'IP statico sopra impostato
if (!WiFi.config(IP_ESP8266, IP_gateway, subnet_mask))
{
Serial.println("Errore nella configurazione");
}
WiFi.begin(ssid, password);//Inizializza le impostazioni di rete della libreria WiFi
delay(1000);
Serial.println(WiFi.status());
while (WiFi.status()!= WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Connesso alla rete WIFI");
Serial.println(IP_ESP8266);
/*
* Per gestire le richieste HTTP in arrivo, dobbiamo specificare quale codice eseguire quando viene
* raggiunto un determinato URL. Per fare ciò, usiamo il metodo on. Questo metodo accetta due parametri.
* Il primo è un percorso URL e il secondo è il nome della funzione che vogliamo eseguire quando viene raggiunto quell'URL.
*/
server.begin(); // inizializzazione del Server Web. Comincia ad "ascoltare" le richieste HTTP
delay(200);
Serial.println("Web Server HTTP in funzione");
server.on("/", handle_OnConnect);
/*
* quando l'oggetto server riceve una richiesta HTTP sul percorso root ( / ) viene eseguita la funzione
* handle_OnConnect (potremmo chiamarla anche in altro modo)
*/
server.onNotFound(handle_NotFound);
timeClient.begin();// inizializzazione dell'NTPClient timeClient
timeClient.setTimeOffset(7200); //7200 secondi
//l'offset tiene conto della differenza oraria dell'Italia rispetto ad UTC (2 ore) quando in Italia vige l'ora legale
}
//
//
void loop()
{
/*
* recupero data e ora dal server NTP. A volte l'NTPClient recupera la data "1 gennaio1970"
* forzando l'aggiornamento questo non accade
*/
while(!timeClient.update())
{
timeClient.forceUpdate();
}
server.handleClient(); // rimane in ascolto sulla porta 80 per le richieste dei clients
delay(1000);
}
//
//
void handle_OnConnect()
{
// faccio 3 letture in modo che i valori letti dal sensore, che non è velocissimo, si stabilizzino
for(int i=0;i<3;i++)
{
h = dht.readHumidity(); // Lettura dell'umidità
t = dht.readTemperature(); // Lettura della temperatura in gradi Celsius
delay(200);
}
String tt=timeClient.getFormattedTime();
unsigned long epoch = timeClient.getEpochTime();
//dal valore di epoch si ricavano giorno, mese ed anno
struct tm *ptm = gmtime ((time_t *)&epoch);
int gg = ptm->tm_mday;
int mm = ptm->tm_mon+1;
String mese=mesi[mm-1];
int aa = ptm->tm_year+1900;
dataora = "Misura del "+String(gg) + " " + mese + " " + String(aa)+" "+tt;
if (isnan(h) || isnan(t)) //Verifica se si presenta un errore di lettura
{
Serial.println("Errore di lettura...");
h=0.0;
t=0.0;
}
String s="Umidità= "+String(h)+" Temperatura="+String(t);
Serial.println(dataora);
Serial.println(s);
server.send(200, "text/html", SendHTML(t,h,dataora));
//invia lo stato 200, cioè l'ok, e una pagina Web, costruita nella funzione SendHTML(), al client/browser
}
void handle_NotFound(){
server.send(404, "text/plain", "Non trovato!!");
//invia lo stato 404, cioè l'errore "not found", e un semplice messaggio di errore al client/browser
}
/*
* risposta al client/browser con il codice HTML che costruisce la pagina web per visualizzare
* data e ora della misura, temperatura ed umidità rilevate dal sensore
*/
String SendHTML(float temperatura,float umidita,String dataoramisura)
{
String s = "<!DOCTYPE html> <html>\n";
s +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
s +="<title>Server Web ESP8266 NodeMCU</title>\n";
s +="<style>html {text-align: center;background-color:#fffff0}\n";
s +="h2 {color: #000080;margin-top:30px;}\n";
s +="p {font-size: 24px;margin-bottom: 10px;}\n";
s +="</style>\n";
s +="</head>\n";
s +="<body>\n";
s +="<h2>ESP8266 NodeMCU<br/>Server Web</h2><br/>\n";
s+=dataoramisura;
s +="<p>Temperatura: ";
s+=temperatura;
s+=" gradi</p>";
s +="<p>Umidità: ";
s+=umidita;
s +="%</p>";
s +="</body>\n";
s +="</html>\n";
return s;
}