LineaMeteoStazione: Technical Guide Receiver, Network and Manager Device – 3
Guest post created with ♥ by Eugenio 🙂|
Choice of Controller Wemos D1 mini Pro ESP8266
In order to receive and manage the data, we will need a controller with WiFi capability that can access the Firebase of Google. I choose the Wemos D1 mini Pro and I also soldered a pressure sensor (BMP180) to it to monitor the atmospheric pressure.
Program ESP8266
The services and management of the data of the weather station are all done by this device. The code used is long and you can find it HERE. First of all, you will need to have installed the Arduino IDE and also the esp8266:
- In your Arduino IDE, go to File> Preferences
- Enter http://arduino.esp8266.com/stable/package_esp8266com_index.json into the “Additional Boards Manager URLs” field. Then, click the “OK” button:
Note: if you already have the ESP32 boards URL, you can separate the URLs with a comma as follows:https://dl.espressif.com/dl/package_esp32_index.json, http://arduino.esp8266.com/stable/package_esp8266com_index.json - Open the Boards Manager. Go to Tools > Board > Boards Manager…
- Search for ESP8266 and press install button for the “ESP8266 by ESP8266 Community“ and wait for the installation to finish.
You can find additional information in this article “WeMos D1 mini (esp8266), pinout, specs and IDE configuration“.
Code Structure
First of all, we define the library used for the code to work a shown below:
///////////////////////////////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
These all libraries can be found in the library manager of the Arduino IDE by searching them or following the link on the code, but some of them are already preinstalled if you installed the ESP module.
These are the declaration in the code with all services and variables. You will need to insert the Firebase details which are the ones that you got from the article talking about the Weather Station. You can also insert your Ota drive details if you wish to use the Ota drive remote function that is explained widely HERE. You will need the API. When an update is required you will need to change the Version number.
////////////////////*********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
The code first checks if a WiFi connection is available and if is not memorized on the device it enters in AP mode thanks to the WiFi manager library, more information here “How to manage dynamic WIFI configuration on esp8266 or esp32“. After entering in AP mode it stays for 5 minutes waiting for a setup otherwise it will restart.
Then we initialize the NTP server by calling timeClient.begin(); and then we start the Firebase authentication with the Firebase.begin function.
We also check if we want to reset the WiFi connection. After that with set up all data in the database by calling the SetupData(); where we write the IP address of the device and we create all database details on the first start. After we the getDataTime(); we get all the configuration of services and the max and min data in case the device loses power the data will remain there. Then we start the bmp180 sensor by calling Wire.begin(); bmp.begin();
We also connect to Blynk if we activated ON on the database before and we check if there is any update if ‘enable’ is in the database under Updates. If it is, it will first check the remote update if a new version is available, otherwise, it will enter in local update mode, as explained in the other article.
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();
}
Loop Code
After the setup we go into the loop, where is the core function of the Device.
If OTA updates are enabled and no remote updates where detected, it will stay for 5 minutes in local mode updates. After that period it will restart if no file were detected.
If no OTA updates are enabled it will start to operate in normal operation. First with readData(); from the database and we process that data to calculate some parameters such as Wind Speed, Rain and Rain Rate and depending on which anemometer and Rain gauge are selected as well. Every 20 seconds we check if the data was sent by the device outside and we also update the time by calling:
if (millis() - previous >= uploadtime)
{
previous = millis();
uploadtime = 20000;
timeClient.update();
if (Firebase.getInt(Weather, "/Time/Communication/DataSent"))
{
DATASENT = Weather.to<int>();
}
checkforUpdates();
}
If yes, we read all data by the following code:
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();
}
}
Once the values are read, we can then calculate some parameters such as DewPoint, Heat Index and others in the next void writeData() and we write some of the values in the database. We also send email notifications if they are enabled. We also calculate the maximum and minimum values.
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();
}
}
After that, we get the time with the gettime() void and we reset the maximum and minimum value if the day is changed:
///////////////////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);
}
}
We also then check if some emails alerts are enabled by calling Email(); every 10 minutes and we have a watchdog in order to avoid restarts of the ESP8266 by functions that take too long to process.
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;
}
}
}
After all that, eventually we activated the lineameteo string if needed and send data to WunderGround, ThingSpeak, WeatherCloud, PWS and 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: Technical Guide Master Device, Sending and Collecting Data
- LineaMeteoStazione: Technical Guide Display
- LineaMeteoStazione: Technical Guide Receiver, Network and Manager Device
- LineaMeteoStazione: The Personalized WiFi Weather Station using ESP32, ESP8266 and Attiny85 with OTA
For the pre-assembled weather station or source of the material please email me Eugenio
eugenioiaquinta@outlook.it