Guest post created with ♥ by Eugenio 🙂|
Scelta del controller Wemos D1 mini Pro ESP8266
Per ricevere e gestire i dati, avremo bisogno di un controller con funzionalità WiFi in grado di accedere a Firebase di Google. Ho scelto il Wemos D1 mini Pro e gli ho anche saldato un sensore di pressione (BMP180) per monitorare la pressione atmosferica.
Programmare l’ESP8266
I servizi e la gestione dei dati della stazione meteo sono tutti svolti da questo dispositivo. Il codice utilizzato è lungo e lo trovi QUI. Prima di tutto, dovrai aver installato l’IDE Arduino e anche l’esp8266:
- Nel tuo IDE Arduino, vai su File> Preferenze
- Inserisci http://arduino.esp8266.com/stable/package_esp8266com_index.json nel campo “Ulteriori URL di Boards Manager”. Quindi, fare clic sul pulsante “OK”:
Nota: se disponi già dell’URL delle schede ESP32, puoi separare gli URL con una virgola come segue: https://dl.espressif.com/dl/package_esp32_index.json, http://arduino.esp8266.com/stable/ package_esp8266com_index.json - Apri Gestione schede. Vai a Strumenti > Board > Board Manager…
- Cerca ESP8266 e premi il pulsante di installazione per “ESP8266 by ESP8266 Community” e attendi il completamento dell’installazione.
Puoi trovare ulteriori informazioni su questo articolo “WeMos D1 mini (esp8266), pinout, specs and IDE configuration“.
Struttura del Codice
Prima di tutto, definiamo le librerie utilizzate per far funzionare il codice come mostrato di seguito:
///////////////////////////////LIBRARY DECLARATION////////////////////////////////////////
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
#include <Arduino.h>
#include <ESP8266httpUpdate.h>
#include <ESP8266WiFi.h>
#include <Arduino.h>
#include "FirebaseESP8266.h" //https://github.com/mobizt/Firebase-ESP8266
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP_Mail_Client.h> //https://github.com/mobizt/ESP-Mail-Client
#include <String.h>
#include <Wire.h>
#include "NTPClient.h" //https://github.com/floatAsNeeded/LineaMeteoStazione-Personalised-Weather-Station/blob/main/NTPClient.zip
#include <WiFiUDP.h>
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
#include <Adafruit_BMP085.h> //https://github.com/adafruit/Adafruit-BMP085-Library
#include <math.h>
Adafruit_BMP085 bmp;
WiFiServer server(80);
WiFiClient client;
WiFiManager wifiManager;
#include <BlynkSimpleEsp8266.h> //https://github.com/blynkkk/blynk-library
Queste librerie possono essere trovate nel gestore delle librerie dell’IDE di Arduino cercandole o seguendo i link sul codice, ma alcune di esse sono già preinstallate se hai installato il modulo ESP.
I dettagli di Firebase sono quelli che hai ottenuto dall’articolo che parla della stazione meteorologica. Puoi anche inserire i dettagli del servizio Ota remoto se desideri utilizzare la funzione remota Ota che è ampiamente spiegata QUI. Avrai bisogno dell’API. Quando è necessario un aggiornamento, sarà necessario modificare il numero di versione.
////////////////////*********EMAIL AND OTA DETAILS************///////////////////////////////////
//OTAREMOTE//
#define ProductKey "" // Replace with your own APIkey
#define Version "1.0.1.3"
#define MakeFirmwareInfo(k, v) "&_FirmwareInfo&k=" k "&v=" v "&FirmwareInfo_&"
unsigned long TIMER = 0;
void update();
//OTA LOCAL//
byte WiFiReset = 0;
const char* host = "esp8266-webupdate";
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
String DEVICE2OTA;
unsigned long TIMEROTA;
//EMAIL//
float TEMPERATUREMAXALERT;
float TEMPERATUREMINALERT;
float TEMPERATUREMAXALERTSECOND;
float TEMPERATUREMINALERTSECOND;
unsigned int HUMIDITYMAXALERT;
unsigned int HUMIDITYMINALERT;
unsigned int HUMIDITYMAXALERTSECOND;
unsigned int HUMIDITYMINALERTSECOND;
float GUSTALERT;
unsigned int UVALERT;
float RAINALERT;
float RAININTENSITYALERT;
float HEATINDEXALERT;
String Language;
String EMAILACCOUNT;
String EmailONOFF;
String EmailAlertONOFF;
String DIRECTIONWIND;
boolean Alert1 = true;
boolean Alert2 = true;
boolean Alert3 = true;
boolean Alert4 = true;
boolean Alert5 = true;
boolean Alert6 = true;
boolean Alert7 = true;
boolean Alert8 = true;
boolean Alert9 = true;
boolean Alert10 = true;
boolean Alert11 = true;
boolean Alert12 = true;
boolean Alert13 = true;
boolean Alert14 = true;
boolean Alert15 = true;
String Alert3ONOFF;
String Alert4ONOFF;
String Alert5ONOFF;
String Alert6ONOFF;
String Alert7ONOFF;
String Alert8ONOFF;
String Alert9ONOFF;
String Alert10ONOFF;
boolean NewAlertLimit = false;
unsigned long checkalert = 0;
unsigned long CheckEmail = 600000;
byte REPORTHOUR;
#define SMTP_HOST "smtp.gmail.com"
/** The smtp port e.g.
25 or esp_mail_smtp_port_25
465 or esp_mail_smtp_port_465
587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT 25
/* The log in credentials */
String AUTHOR_EMAIL;
String AUTHORPASSWORD;
/* The SMTP Session object used for Email sending */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
////////////////////*********FIREBASE DETAILS************///////////////////////////////////
#define FIREBASE_HOST "" // the project name address from firebase id
#define FIREBASE_AUTH "" // the secret key generated from firebase
FirebaseData Weather;
//////////////////////*********NTP SERVER************//////////////////////////////////////
// Define NTP properties
#define NTP_OFFSET 60 * 60 // In seconds
#define NTP_INTERVAL 60 * 1000 // In miliseconds
#define NTP_ADDRESS "pool.ntp.org" // "ca.pool.ntp.org" // change this to whatever pool is closest (see ntp.org)
// Set up the NTP UDP client
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_ADDRESS , NTP_OFFSET, NTP_INTERVAL);
///////////////////////*********BLYNK DETAILS************//////////////////////////////////
String APIBLYNK;
String ServerBlynk;
String BLYNKONOFF;
int Port;
////////////////////*********THINGSPEAK DETAILS************////////////////////////////////
String myWriteAPIKey;
const char* serverThingSpeak = "api.thingspeak.com";
////////////////////*********WEATHERCLOUD************////////////////////////////////
String Weathercloud_ID;
String Weathercloud_KEY;
const int httpPort = 80;
const char* Weathercloud = "api.weathercloud.net"; //http://api.weathercloud.net
////////////////////*********WUNDERGROUND************////////////////////////////////
char serverWU [] = "rtupdate.wunderground.com";
char WEBPAGE [] = "GET /weatherstation/updateweatherstation.php?";
String ID;
String Key;
////////////////////*********PWS************////////////////////////////////
char serverPWS [] = "pwsupdate.pwsweather.com";
char WEBPAGEPWS [] = "GET /api/v1/submitwx?";
String IDPWS;
String APIPWS;
////////////////////*********LINEAMETEO************////////////////////////////////
String Latitude;
String Longitude;
String City;
String Altitude;
String StringLineaMeteo;
//DEWPOINT CALCULATION CONSTANTS//
#define c1 -8.78469475556
#define c2 1.61139411
#define c3 2.33854883889
#define c4 -0.14611605
#define c5 -0.012308094
#define c6 -0.0164248277778
#define c7 0.002211732
#define c8 0.00072546
#define c9 -0.000003582
//////////TEMPERATURE///////////
float OffsetTemp;
float temp;
float tempSHT2x;
float tempinside;
//TEMPERATURE EXTREMES//
float maxTemp;
float minTemp;
//////////HUMIDITY/////////////
int OffsetHum;
int humiditySHT2x;
int humidity;
int humidityinside;
//HUMIDITY EXTREMES//
int maxHumidity;
int minHumidity;
//////////PRESSURE/////////////
float pressurehpa;
int CALIBRATION;
////////////RAIN////////////////
float mmGoccia; // tipping bucket count in mm
float mmPioggia;
float mmPioggiaLast = 0;
float rainrate = 0; // real-time rainrate
float rainrateMax = 0; // daily rainrateMax
byte rainratedetect = 0;
int rainrateMaxIntensity = 0;
byte PluvioFlag = 0; // detect interrupt of rain
byte rainrateI2C = 0;
byte rainrateMaxI2C = 0;
byte rainrateMaxI2CIntensity = 0;
////////////WIND/////////////////
int WindDirectionMisol;
int WindDirectionDavis;
float GustMax;
int Offset; // adjust wind direction value
byte Rotations;
byte GustRotations;
unsigned int average = 3000; // sample time for wind speed
float constant; // formula calculation
float WindSpeed; // speed km/h
float GustNow = 0;
int VaneValue; // raw analog value from wind vane
int Direction; // translated 0 - 360 direction
int CalDirection; // converted value with offset applied
byte AnemometerType;
////////////DEWPOINT///////////////
float dewPoint; // variabile del punto di rugiada
float dewPointIN;
//DEW POINT EXTREMES//
//float dewPointmax;
//float dewPointmin;
////////////HEATINDEX///////////////
float heatIndex; // variabile dell'indice di calore
float heatIndexIN;
//float heatIndexMax;
////////////WINDCHILL///////////////
float windchill; // variabile del raffreddamento causato dal vento
//float Windchillmin;
/////////////LIGHT////////////////
float UVindex;
float Lux;
float SolarRadiation;
float CalibrationRadiation;
float CalibrationUV;
//int UVmax;
/////////////AIRQUALITY////////////////
int AIRQUALITY;
////TIMING AND OTHER VARIALABLES////
unsigned long uploadtime = 0;
unsigned long timeout;
bool res;
unsigned long previous = 0;
unsigned long previousTHINGSPEAK;
unsigned long previousWEATHERCLOUD;
unsigned long previousWUNDERGROUND;
unsigned long previousBLYNK;
unsigned long previousPWS;
unsigned long UPLOADPWS = 300000;
unsigned long UPLOADTHINGSPEAK;
unsigned long UPLOADWEATHERCLOUD;
unsigned long UPLOADWUNDERGROUND;
unsigned long UPLOADBLYNK;
byte CurrentDay;
boolean readvalues = false;
byte RESETDATA = 0;
byte DATASENT;
int TIMEZONE;
long TIMEZONEINSECONDS;
float BatteryVoltage;
String AutomaticBatteryManagement;
byte HOURS;
byte PREVIOUSHOURS;
byte PREVIOUSREPORTHOUR;
Setup Code
Il codice prima verifica se è disponibile una connessione WiFi e se non è memorizzato sul dispositivo entra in modalità AP grazie alla libreria del gestore WiFi, maggiori informazioni consulta qui “How to manage dynamic WIFI configuration on esp8266 or esp32“. Dopo essere entrato in modalità AP rimarrà per 5 minuti in attesa di un nuovo firmware, altrimenti si riavvierà.
Quindi inizializziamo il server NTP chiamando timeClient.begin(); e poi avviamo l’autenticazione Firebase con la funzione Firebase.begin.
Controlliamo anche se vogliamo fare un reset delle credenziali WiFi salvate. Dopodiché, impostiamo tutti i dati nel database chiamando SetupData(); dove scriviamo tutti i dettagli del database al primo avvio. Poi, usiamo getDataTime(); in cui otteniamo tutta la configurazione dei servizi e i dati massima e minima, cosi nel caso in cui il dispositivo perda alimentazione i dati rimarranno lì. Quindi avviamo il sensore bmp180 chiamando Wire.begin(); bmp.begin();
Ci colleghiamo anche a Blynk se abbiamo attivato ON sul database in precedenza e controlliamo se c’è qualche aggiornamento se ‘enable’ è scritto nel database sotto gli aggiornamenti. Se lo è, controllerà prima da remoto se è disponibile una nuova versione del firmware, altrimenti entrerà in modalità di aggiornamento locale OTA.
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
//wifiManager.resetSettings();
wifiManager.setConfigPortalTimeout(300);
WiFi.begin();
timeout = millis();
while (WiFi.status() != WL_CONNECTED) {
delay(250);
//Serial.print(".");
if (millis() - timeout > 25000)
{
res = wifiManager.autoConnect("LineaMeteoStazioneR", "LaMeteo2005");
if (!res) {
//Serial.println("Failed to connect");
//ESP.deepSleep(15 * 1000000, WAKE_RF_DEFAULT);
ESP.restart();
}
}
}
timeClient.begin(); // Start the NTP UDP client
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); // connect to firebase
Serial.println(Weather.errorReason());
Firebase.reconnectWiFi(true);
Firebase.setMaxRetry(Weather, 2);
//Weather.setBSSLBufferSize(1024, 512);
//Set the size of HTTP response buffers in the case where we want to work with large data.
//Weather.setResponseSize(1024);
//char auth[] = APIBLYNK.c_str();WiFi.SSID().c_str()
if (Firebase.getInt(Weather, "/Connection/DEVICE2/ResetWiFi"))
{
WiFiReset = Weather.to<int>();
}
if (WiFiReset == 1)
{
WiFiReset = 0;
Firebase.setInt(Weather, "/Connection/DEVICE2/ResetWiFi", 0);
wifiManager.resetSettings();
WiFi.mode(WIFI_STA);
wifiManager.setConfigPortalTimeout(300);
WiFi.begin();
timeout = millis();
while (WiFi.status() != WL_CONNECTED) {
delay(250);
//Serial.print(".");
if (millis() - timeout > 10000)
{
res = wifiManager.autoConnect("LineaMeteoStazioneR", "LaMeteo2005");
if (!res) {
ESP.restart();
}
}
}
}
Firebase.deleteNode(Weather, "/Connection/DEVICE2/UpdateHere");
Firebase.setString(Weather, "/Connection/DEVICE2/Version", Version);
/*if (Firebase.getInt(Weather, "/Test/Restart"))
{
Countrestart = Weather.to<int>();
}
Countrestart++;
Firebase.setInt(Weather, "/Test/Restart", Countrestart);*/
SetupData();
getDataTime();
Wire.begin();
bmp.begin();
smtp.debug(1);
if (BLYNKONOFF == "ON")
{
//Blynk.begin(APIBLYNK.c_str(), WiFi.SSID().c_str(), WiFi.psk().c_str(), ServerBlynk.c_str(), Port);
Blynk.config(APIBLYNK.c_str(), ServerBlynk.c_str(), Port);
Blynk.connect();
}
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
if (Firebase.getString(Weather, "/Connection/DEVICE2/Update"))
{
DEVICE2OTA = Weather.to<const char *>();
}
if (DEVICE2OTA == "enable")
{
Firebase.setString(Weather, "/Connection/DEVICE2/Update", "disable");
delay(50);
update();
}
if (DEVICE2OTA == "enable")
{
MDNS.begin(host);
httpUpdater.setup(&httpServer);
httpServer.begin();
MDNS.addService("http", "tcp", 80);
Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host);
Firebase.setString(Weather, "/Connection/DEVICE2/Update", "disable");
delay(50);
Firebase.setString(Weather, "/Connection/DEVICE2/UpdateHere", String(WiFi.localIP().toString() + "/update"));
delay(50);
TIMEROTA = millis();
}
if (StringLineaMeteo == "enable" && DEVICE2OTA != "enable")
{
server.begin();
}
TIMEZONEINSECONDS = TIMEZONE * 3600;
timeClient.update();
timeClient.setTimeOffset(TIMEZONEINSECONDS);
timeClient.getFullFormattedTime();
HOURS = timeClient.getHours();
}
Codice Loop
Dopo la configurazione entriamo nel loop, dove si trova il funzionamento principale del dispositivo.
Se gli aggiornamenti OTA sono abilitati e non viene rilevato nessuno aggiornamento remoto, rimarrà per 5 minuti in attesa di qualche aggiornamento locale. Dopo tale periodo si riavvierà se non è stato rilevato alcun file.
Se nessun aggiornamento OTA è abilitato, inizierà nella sua modalità operativa normale. Con readData(); dal database, elaboriamo i dati inviati dall’unità esterna per calcolare alcuni parametri come velocità del vento, pioggia e intensità di pioggia e in base a quale anemometro e pluviometro vengono selezionati modificheremo i calcoli. Ogni 20 secondi controlliamo se i dati sono stati inviati dal dispositivo all’esterno e aggiorniamo anche l’ora e controlliamo anche se la modalità di aggiornamento OTA è stata attivata, chiamando:
if (millis() - previous >= uploadtime)
{
previous = millis();
uploadtime = 20000;
timeClient.update();
if (Firebase.getInt(Weather, "/Time/Communication/DataSent"))
{
DATASENT = Weather.to<int>();
}
checkforUpdates();
}
Se sì, leggiamo tutti i dati con il seguente codice:
if (DATASENT == 1)
{
Firebase.setInt(Weather, "/Time/Communication/DataSent", 0);
DATASENT = 0;
readvalues = true;
if (AnemometerType == 1)
{
readDavisAnemometer ();
}
else if (AnemometerType == 2)
{
readAnemometer ();
}
readRain();
readPressure();
readTemperatureHumidity();
readInsideValues();
readLight();
readAirQuality();
checkBatteryVoltage();
readEmailLanguage();
}
}
Una volta letti i valori, possiamo quindi calcolare alcuni parametri come DewPoint, Heat Index e altri nel prossimo void writeData() e scriviamo alcuni dei valori nel database. Inviamo anche notifiche e-mail se sono abilitate. Calcoliamo anche i valori massimi e minimi.
void writeData()
{
if (readvalues == true)
{
readvalues = false;
dewPoint = (temp - (14.55 + 0.114 * temp) * (1 - (0.01 * humidity)) - pow(((2.5 + 0.007 * temp) * (1 - (0.01 * humidity))), 3) - (15.9 + 0.117 * temp) * pow((1 - (0.01 * humidity)), 14)); //equazione per il calcolo del dewpoint
//INSIDE//
dewPointIN = (tempinside - (14.55 + 0.114 * tempinside) * (1 - (0.01 * humidityinside)) - pow(((2.5 + 0.007 * tempinside) * (1 - (0.01 * humidityinside))), 3) - (15.9 + 0.117 * tempinside) * pow((1 - (0.01 * humidityinside)), 14)); //equazione per il calcolo del dewpoint
if (temp < 11)
{
windchill = (13.12 + 0.6215 * temp) - (11.37 * pow(WindSpeed, 0.16)) + (0.3965 * temp * pow(WindSpeed, 0.16));//equazione per il calcolo del windchill
}
else
{
windchill = temp;
}
if (temp > 21)
{
heatIndex = c1 + (c2 * temp) + (c3 * humidity) + (c4 * temp * humidity) + (c5 * sq(temp)) + (c6 * sq(humidity)) + (c7 * sq(temp) * humidity) + (c8 * temp * sq(humidity)) + (c9 * sq(temp) * sq(humidity));
}
else if (temp <= 21)
{
heatIndex = temp;
}
//INSIDE//
if (tempinside > 21)
{
heatIndexIN = c1 + (c2 * tempinside) + (c3 * humidityinside) + (c4 * tempinside * humidityinside) + (c5 * sq(tempinside)) + (c6 * sq(humidityinside)) + (c7 * sq(tempinside) * humidityinside) + (c8 * tempinside * sq(humidityinside)) + (c9 * sq(tempinside) * sq(humidityinside));
}
else if (tempinside <= 21)
{
heatIndexIN = tempinside;
}
SolarRadiation = (Lux / 120) * CalibrationRadiation;
if (SolarRadiation < 1)
{
SolarRadiation = 0;
}
Firebase.setFloat(Weather, "/Light/SolarRadiation", SolarRadiation);
writePressure();
writeRain();
writeWind();
maxminvalues();
EMAILNOTIFICATION();
}
}
Dopodiché, otteniamo l’ora con gettime() void e resettiamo il valore massimo e minimo quando il giorno cambia:
///////////////////GET TIME//////////////////////////
void gettime()
{
TIMEZONEINSECONDS = TIMEZONE * 3600;
//timeClient.update();
timeClient.setTimeOffset(TIMEZONEINSECONDS);
timeClient.getFullFormattedTime();
HOURS = timeClient.getHours();
if (CurrentDay != timeClient.getDate() && timeClient.getYear() != 1970)
{
CurrentDay = timeClient.getDate();
Alert2 = true;
Alert11 = true;
Alert13 = true;
Alert14 = true;
Alert15 = true;
maxHumidity = humidity;
minHumidity = humidity;
maxTemp = temp;
minTemp = temp;
mmPioggia = 0;
GustMax = 0;
rainrateMax = 0;
Firebase.setInt(Weather, "/Time/CurrentDay", CurrentDay);
Firebase.setInt(Weather, "/SHT3x/Humidity/HumidityMax", maxHumidity);
Firebase.setInt(Weather, "/SHT3x/Humidity/HumidityMin", minHumidity);
Firebase.setFloat(Weather, "/SHT3x/Temperature/TemperatureMax", maxTemp);
Firebase.setFloat(Weather, "/SHT3x/Temperature/TemperatureMin", minTemp);
Firebase.setFloat(Weather, "/Rain/Rain24H", mmPioggia);
Firebase.setFloat(Weather, "/Rain/RainRateMax", rainrateMax);
Firebase.setFloat(Weather, "/Wind/GustMax", GustMax);
}
}
Quindi controlliamo anche se alcuni avvisi email sono abilitati chiamando Email(); ogni 10 minuti e abbiamo un watchdog per evitare il riavvio dell’ESP8266, in caso ci siano funzioni bloccanti che facciano rallentare l’ESP8266:
ESP.wdtFeed(); // feeds the dog
delay(0);
void Email()
{
if (millis() - checkalert >= CheckEmail)
{
ESP.wdtFeed(); // feeds the dog
delay(0);
checkalert = millis();
BATTERYMANAGEMENT();
if (EmailONOFF == "ON")
{
if (Firebase.getInt(Weather, "/Services/EmailAlert/ReportHour"))
{
REPORTHOUR = Weather.to<int>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/EmailReport"))
{
EmailONOFF = Weather.to<const char *>();
}
}
else
{
if (Firebase.getString(Weather, "/Services/EmailAlert/EmailReport"))
{
EmailONOFF = Weather.to<const char *>();
}
}
if (EmailAlertONOFF == "ON")
{
if (Firebase.getString(Weather, "/Services/EmailAlert/EmailAlert"))
{
EmailAlertONOFF = Weather.to<const char *>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/SHT3x/Temperature/Enable"))
{
Alert3ONOFF = Weather.to<const char *>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/SHT2x/Temperature/Enable"))
{
Alert4ONOFF = Weather.to<const char *>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/SHT3x/Humidity/Enable"))
{
Alert5ONOFF = Weather.to<const char *>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/SHT2x/Humidity/Enable"))
{
Alert6ONOFF = Weather.to<const char *>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/Gust/Enable"))
{
Alert7ONOFF = Weather.to<const char *>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/Rain/Enable"))
{
Alert8ONOFF = Weather.to<const char *>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/UV/Enable"))
{
Alert9ONOFF = Weather.to<const char *>();
}
if (Firebase.getString(Weather, "/Services/EmailAlert/HeatIndex/Enable"))
{
Alert10ONOFF = Weather.to<const char *>();
}
if (Alert3ONOFF == "ON")
{
if (Firebase.getFloat(Weather, "/Services/EmailAlert/SHT3x/Temperature/TemperatureMax"))
{
TEMPERATUREMAXALERT = Weather.to<float>();
}
if (Firebase.getFloat(Weather, "/Services/EmailAlert/SHT3x/Temperature/TemperatureMin"))
{
TEMPERATUREMINALERT = Weather.to<float>();
}
}
if (Alert4ONOFF == "ON")
{
if (Firebase.getFloat(Weather, "/Services/EmailAlert/SHT2x/Temperature/TemperatureMax"))
{
TEMPERATUREMAXALERTSECOND = Weather.to<float>();
}
if (Firebase.getFloat(Weather, "/Services/EmailAlert/SHT2x/Temperature/TemperatureMin"))
{
TEMPERATUREMINALERTSECOND = Weather.to<float>();
}
}
if (Alert5ONOFF == "ON")
{
if (Firebase.getInt(Weather, "/Services/EmailAlert/SHT3x/Humidity/HumidityMax"))
{
HUMIDITYMAXALERT = Weather.to<int>();
}
if (Firebase.getInt(Weather, "/Services/EmailAlert/SHT3x/Humidity/HumidityMin"))
{
HUMIDITYMINALERT = Weather.to<int>();
}
}
if (Alert6ONOFF == "ON")
{
if (Firebase.getInt(Weather, "/Services/EmailAlert/SHT2x/Humidity/HumidityMax"))
{
HUMIDITYMAXALERTSECOND = Weather.to<int>();
}
if (Firebase.getInt(Weather, "/Services/EmailAlert/SHT2x/Humidity/HumidityMin"))
{
HUMIDITYMINALERTSECOND = Weather.to<int>();
}
}
if (Alert7ONOFF == "ON")
{
if (Firebase.getFloat(Weather, "/Services/EmailAlert/Gust/Gust"))
{
GUSTALERT = Weather.to<float>();
}
}
if (Alert8ONOFF == "ON")
{
if (Firebase.getFloat(Weather, "/Services/EmailAlert/Rain/Rain"))
{
RAINALERT = Weather.to<float>();
}
if (Firebase.getFloat(Weather, "/Services/EmailAlert/Rain/RainIntensity"))
{
RAININTENSITYALERT = Weather.to<float>();
}
}
if (Alert9ONOFF == "ON")
{
if (Firebase.getInt(Weather, "/Services/EmailAlert/UV/UV"))
{
UVALERT = Weather.to<int>();
}
}
if (Alert10ONOFF == "ON")
{
if (Firebase.getFloat(Weather, "/Services/EmailAlert/HeatIndex/HeatIndex"))
{
HEATINDEXALERT = Weather.to<float>();
}
}
NewAlertLimit = true;
}
else
{
if (Firebase.getString(Weather, "/Services/EmailAlert/EmailAlert"))
{
EmailAlertONOFF = Weather.to<const char *>();
}
}
if (HOURS != PREVIOUSREPORTHOUR)
{
PREVIOUSREPORTHOUR = HOURS;
Alert1 = true;
Alert3 = true;
Alert4 = true;
Alert4 = true;
Alert5 = true;
Alert6 = true;
Alert7 = true;
Alert8 = true;
Alert9 = true;
Alert10 = true;
Alert12 = true;
}
}
}
Dopo tutto ciò, alla fine attiviamo la stringa lineameteo se necessario e inviato i dati a WunderGround, ThingSpeak, WeatherCloud, PWS e Blynk.
void loop()
{
if (DEVICE2OTA == "enable")
{
httpServer.handleClient();
MDNS.update();
if (millis() - TIMEROTA > 300000)
{
ESP.restart();
}
}
else
{
readData();
writeData();
gettime();
Email();
if (StringLineaMeteo == "enable")
{
lineameteo();
}
if (DEVICE2OTA == "enable")
{
ESP.restart();
}
if (millis() - previousWEATHERCLOUD >= UPLOADWEATHERCLOUD)
{
previousWEATHERCLOUD = millis();
push_to_weathercloud();
// pws();
}
if (millis() - previousWUNDERGROUND >= UPLOADWUNDERGROUND)
{
previousWUNDERGROUND = millis();
wunderground();
}
if (BLYNKONOFF == "ON")
{
if (millis() - previousBLYNK >= UPLOADBLYNK)
{
previousBLYNK = millis();
BlynkFunction();
}
}
if (millis() - previousPWS >= UPLOADPWS)
{
previousPWS = millis();
pws();
}
THINGSPEAK();
}
}
Links
- LineaMeteoStazione: Guida Tecnica Dispositivo Master, Invio e Raccolta Dati
- LineaMeteoStazione: Guida Tecnica Display
- LineaMeteoStazione: Guida Tecnica Ricevitore, rete e dispositivo di gestione
- LineaMeteoStazione: La Stazione Meteo Personalizzabile con ESP32, ESP8266, Attiny85 e aggiornamenti OTA
Per la stazione metereologica pre-assemblata o l’origine dei materiale per favore scrivimi Eugenio
eugenioiaquinta@outlook.it