//****************************************************************
//****************************************************************
//
// CONFIGURARE LA SCHEDA COME ESP32 DEV MODULE
//
//****************************************************************
//****************************************************************
#include <SPI.h>
#include <TFT_eSPI.h> // Includi la libreria
#include <WiFi.h>
#include "time.h"
#include "esp_sntp.h"
#include "esp32_small.h"
//#include "clock.h"
#include "wifi_24.h"
//ICONE LAMMA METEO
#include "LAMMA_img/sereno.c"
#include "LAMMA_img/sereno_luna.c"
#include "LAMMA_img/coperto.c"
#include "LAMMA_img/coperto2.c"
#include "LAMMA_img/coperto_luna.c"
#include "LAMMA_img/foschia.c"
#include "LAMMA_img/foschia_luna.c"
#include "LAMMA_img/nebbia.c"
#include "LAMMA_img/neve.c"
#include "LAMMA_img/neve_debole.c"
#include "LAMMA_img/neve_sole.c"
#include "LAMMA_img/neve_sole_luna.c"
#include "LAMMA_img/neve_sole2.c"
#include "LAMMA_img/neve_sole2_luna.c"
#include "LAMMA_img/nuvoloso.c"
#include "LAMMA_img/nuvoloso_luna.c"
#include "LAMMA_img/pioggia_debole.c"
#include "LAMMA_img/pioggia_debole1.c"
#include "LAMMA_img/pioggia_neve.c"
#include "LAMMA_img/pioggia_sole2.c"
#include "LAMMA_img/pioggia_sole2_luna.c"
#include "LAMMA_img/pioggia_sole3.c"
#include "LAMMA_img/pioggia_sole3_luna.c"
#include "LAMMA_img/poco_nuvoloso.c"
#include "LAMMA_img/poco_nuvoloso_luna.c"
#include "LAMMA_img/stratificata2.c"
#include "LAMMA_img/stratificata2_luna.c"
#include "LAMMA_img/temporale.c"
#include "LAMMA_img/temporale_pom.c"
#include "LAMMA_img/temporale_pom_luna.c"
#include "LAMMA_img/question.c"
#define WEATHERSRV_IP "192.168.1.122" //macchina da cui scaricare i dati LAMMA (PowerPi)
#define WEATHERSRV_PORT 8555
#define FW_VER "v1.2"
//time zone
#define MY_TZ "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00" //timezone desiderata
#define NTP_SERVER "ntp1.inrim.it" //server ntp
const char *ssid = "CASA2";
const char *password = "********";
String giornoSett[] = { "dom", "lun", "mar", "mer", "gio", "ven", "sab"};
/*const char *ntpServer1 = "ntp1.inrim.it";
const char *ntpServer2 = "ntp2.inrim.it";
const long gmtOffset_sec = 0;
const int daylightOffset_sec = 3600;*/
//const char *time_zone = "CET-1CEST,M3.5.0,M10.5.0/3"; // TimeZone rule for Europe/Rome including daylight adjustment rules (optional)
// Crea un'istanza della libreria
TFT_eSPI tft = TFT_eSPI();
WiFiClient LAMMA_clt;
//struttura per dati LAMMA
typedef struct
{
String desMeteo;
String nomeImg;
} dLAMMA;
dLAMMA LDati[0];
int currFascia;
int oldFascia;
void setup()
{
currFascia = 0;
oldFascia = -1;
//ESP_Watchdog_Setup();
Serial.begin(115200);
Serial.println("Avvio test display ST7789...");
// Inizializza il display
tft.init();
tft.setRotation(3); // Prova 0, 1, 2, 3 per la rotazione desiderata
// Opzionale: accendi la retroilluminazione se hai definito TFT_BL
#ifdef TFT_BL
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
#endif
Serial.println("Display inizializzato.");
// Riempie lo schermo di nero
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextSize(1);
//tft.drawString("Connessione a " + String(ssid), 10, 10, 2);
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
// Calcola la posizione centrale o desiderata per il logo
int xPos = (tft.width() - 72) / 2;
int yPos = (tft.height() - 112) / 2;
// 2. Disegna la Bitmap
// pushImage(x, y, larghezza, altezza, array_dati)
// Swap the colour byte order when rendering
tft.setSwapBytes(true);
// Draw the icons
tft.pushImage(xPos, yPos, 72, 112, esp32_small);
tft.drawString("ESP32 powered - " + String(FW_VER), 160, 155, 2);
delay(500);
/**
* NTP server address could be acquired via DHCP,
*
* NOTE: This call should be made BEFORE esp32 acquires IP address via DHCP,
* otherwise SNTP option 42 would be rejected by default.
* NOTE: configTime() function call if made AFTER DHCP-client run
* will OVERRIDE acquired NTP server address
*/
esp_sntp_servermode_dhcp(1); // (optional)
while (WiFi.status() != WL_CONNECTED)
{
delay(150);
//yield();
Serial.print(".");
}
// 3. Ottieni l'indirizzo IP come oggetto IPAddress
IPAddress localIP = WiFi.localIP();
tft.fillScreen(TFT_BLACK);
tft.drawLine(0, 27, 320, 27, tft.color565(150, 150, 150));
tft.drawLine(0, 145, 320, 145, tft.color565(150, 150, 150));
//tft.drawString(localIP.toString(), 200, 155, 2);
tft.drawString(localIP.toString(), 160, 5, 2);
tft.drawString(NTP_SERVER, 20, 5, 2);
Serial.println(" CONNECTED");
//tft.pushImage(0, 50, 64, 64, orologio);
//tft.pushImage(0, 40, 72, 68, pioggia_debole);
if (WiFi.status() == WL_CONNECTED)
{
tft.pushImage(280, 0, 24, 24, wifi_24);
// set notification call-back function
sntp_set_time_sync_notification_cb(timeavailable);
/**
* This will set configured ntp servers and constant TimeZone/daylightOffset
* should be OK if your time zone does not need to adjust daylightOffset twice a year,
* in such a case time adjustment won't be handled automagically.
*/
//configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
configTime(0, 0, NTP_SERVER); // 0, 0 because we will use TZ in the next line
setenv("TZ", MY_TZ, 1); // Set environment variable with your time zone
tzset();
}
//ScaricaDatiLAMMA();
//configTzTime("Europe/Rome", "ntp1.inrim.it");
}
void loop()
{
struct tm timeinfo;
timeinfo = printLocalTime();
if (IsWeather(timeinfo))
{
ScaricaDatiLAMMA();
}
//yield();
//tft.drawString(String(currFascia), 300, 135, 2);
delay(50);
}
tm printLocalTime()
{
struct tm timeinfo;
String ora="";
String sec="";
String data="";
uint16_t coloreTesto = 0;
int gs = 0;
int ss = 0;
if (!getLocalTime(&timeinfo))
{
Serial.println("[printLocalTime] orario non ancora disponibile");
return timeinfo;
}
ora = ConvertiHHMM(timeinfo);
sec = ConvertiSEC(timeinfo);
ss = timeinfo.tm_sec;
data = ConvertiData(timeinfo);
gs = timeinfo.tm_wday;
SecBar(ss);
// Imposta i colori e la dimensione del testo
tft.setTextColor(TFT_WHITE, TFT_BLACK); // Colore testo, Colore sfondo
//tft.setTextSize(2); // Dimensione 2
//ora
tft.setTextSize(4);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.drawString(ora, 85, 55, 1);
coloreTesto = tft.color565(255, 80, 80);
tft.setTextColor(coloreTesto, TFT_BLACK);
tft.drawString(sec, 207, 55, 1);
//data
tft.setTextSize(3);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.drawString(data, 93, 100, 1);
//ripristino il valore di default
tft.setTextSize(2);
tft.drawString(giornoSett[gs], 15, 112, 2);
//Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
return timeinfo;
}
void SecBar(int sec)
{
//disegna la barra di avanzamento dei secondi
int16_t col = TFT_ORANGE;
tft.drawRect(178, 158, 123, 14, col);
if (sec == 0)
tft.fillRect(180, 160, 120, 10, TFT_BLACK);
else
tft.fillRect(180, 160, sec * 2, 10, col);
}
String ConvertiData(const struct tm &timeinfo)
{
char timeStringBuff[11];
strftime(timeStringBuff, sizeof(timeStringBuff), "%d/%m/%Y", &timeinfo);
return String(timeStringBuff);
}
String ConvertiHHMM(const struct tm &timeinfo)
{
//ritorna una stringa HH:MM
char timeStringBuff[6];
strftime(timeStringBuff, sizeof(timeStringBuff), "%H:%M", &timeinfo);
return String(timeStringBuff);
}
String ConvertiSEC(const struct tm &timeinfo)
{
//ritorna una stringa contenente solo i secondi
char timeStringBuff[4];
strftime(timeStringBuff, sizeof(timeStringBuff), ":%S", &timeinfo);
return String(timeStringBuff);
}
String ConvertiOra(const struct tm &timeinfo)
{
char timeStringBuff[9];
strftime(timeStringBuff, sizeof(timeStringBuff), "%H:%M:%S", &timeinfo);
return String(timeStringBuff);
}
// Callback function (gets called when time adjusts via NTP)
void timeavailable(struct timeval *t)
{
struct tm timeinfo;
String ora="";
if (!getLocalTime(&timeinfo))
{
Serial.println("[timeavailable] orario non ancora disponibile");
return;
}
else
{
ora = ConvertiOra(timeinfo);
tft.setTextSize(1);
tft.drawString("ultimo agg.to: " + ora, 20, 155, 2);
}
Serial.println("effettuato sync con NTP!");
printLocalTime();
}
void ScaricaDatiLAMMA()
{
//scarica i dati LAMMA da PowerPi
String line="";
dLAMMA LD;
if (WiFi.status() == WL_CONNECTED)
{
if (!LAMMA_clt.connect(WEATHERSRV_IP, WEATHERSRV_PORT))
{
//ClearDisplay();
tft.pushImage(0, 40, 72, 72, question);
Serial.println("PowerPi non raggiungibile");
}
else
{
Serial.println("Connesso a LAMMA_srv");
LAMMA_clt.setTimeout(3500);
LAMMA_clt.print("*");
while (LAMMA_clt.connected() || LAMMA_clt.available())
{
if (LAMMA_clt.available())
{
line = LAMMA_clt.readStringUntil('*');
//String line = LAMMA_clt.read();
Serial.println(line);
}
}
LAMMA_clt.stop();
//estrae i dati dalla stringa ricevuta
LD= ConvertiDatiLAMMA(line);
//visualizza dati meteo
//ClearDisplay();
LDati[0].nomeImg= LD.nomeImg;
//descrMeteo= LD.desMeteo;
//seleziono la bitmap da mostrare
if (LDati[0].nomeImg=="sereno") tft.pushImage(0, 40, 72, 68, sereno);
if (LDati[0].nomeImg=="sereno_luna") tft.pushImage(0, 40, 72, 68, sereno_luna);
if (LDati[0].nomeImg=="coperto") tft.pushImage(0, 40, 72, 68, coperto);
if (LDati[0].nomeImg=="coperto_luna") tft.pushImage(0, 40, 72, 68, coperto_luna);
if (LDati[0].nomeImg=="coperto2") tft.pushImage(0, 40, 72, 68, coperto2);
if (LDati[0].nomeImg=="foschia") tft.pushImage(0, 40, 72, 68, foschia);
if (LDati[0].nomeImg=="foschia_luna") tft.pushImage(0, 40, 72, 68, foschia_luna);
if (LDati[0].nomeImg=="nebbia") tft.pushImage(0, 40, 72, 68, nebbia);
if (LDati[0].nomeImg=="nebbia_luna") tft.pushImage(0, 40, 72, 68, nebbia);
if (LDati[0].nomeImg=="neve") tft.pushImage(0, 40, 72, 68, neve);
if (LDati[0].nomeImg=="neve_luna") tft.pushImage(0, 40, 72, 68, neve);
if (LDati[0].nomeImg=="neve_debole") tft.pushImage(0, 40, 72, 68, neve_debole);
if (LDati[0].nomeImg=="neve_debole_luna") tft.pushImage(0, 40, 72, 68, neve_debole);
if (LDati[0].nomeImg=="neve_sole") tft.pushImage(0, 40, 72, 68, neve_sole);
if (LDati[0].nomeImg=="neve_sole_luna") tft.pushImage(0, 40, 72, 68, neve_sole_luna);
if (LDati[0].nomeImg=="neve_sole2") tft.pushImage(0, 40, 72, 68, neve_sole2);
if (LDati[0].nomeImg=="neve_sole2_luna") tft.pushImage(0, 40, 72, 68, neve_sole2_luna);
if (LDati[0].nomeImg=="nuvoloso") tft.pushImage(0, 40, 72, 68, nuvoloso);
//if (LDati[0].nomeImg=="nuvoloso nuvoloso") tft.pushImage(0, 40, 72, 68, nuvoloso);
if (LDati[0].nomeImg=="nuvoloso_luna") tft.pushImage(0, 40, 72, 68, nuvoloso_luna);
//if (LDati[0].nomeImg=="nuvoloso nuvoloso_luna") tft.pushImage(0, 40, 72, 68, nuvoloso_luna);
if (LDati[0].nomeImg=="pioggia_debole") tft.pushImage(0, 40, 72, 68, pioggia_debole);
if (LDati[0].nomeImg=="pioggia_debole1") tft.pushImage(0, 40, 72, 68, pioggia_debole1);
if (LDati[0].nomeImg=="pioggia_debole1_luna") tft.pushImage(0, 40, 72, 68, pioggia_debole1);
if (LDati[0].nomeImg=="pioggia_debole_luna") tft.pushImage(0, 40, 72, 68, pioggia_sole2_luna);
if (LDati[0].nomeImg=="pioggia_neve") tft.pushImage(0, 40, 72, 68, pioggia_neve);
if (LDati[0].nomeImg=="pioggia_neve_luna") tft.pushImage(0, 40, 72, 68, pioggia_neve);
if (LDati[0].nomeImg=="pioggia_sole2") tft.pushImage(0, 40, 72, 68, pioggia_sole2);
if (LDati[0].nomeImg=="pioggia_sole2_luna") tft.pushImage(0, 40, 72, 68, pioggia_sole2_luna);
if (LDati[0].nomeImg=="pioggia_sole3") tft.pushImage(0, 40, 72, 68, pioggia_sole3);
if (LDati[0].nomeImg=="pioggia_sole3_luna") tft.pushImage(0, 40, 72, 68, pioggia_sole3_luna);
if (LDati[0].nomeImg=="poco_nuvoloso") tft.pushImage(0, 40, 72, 68, poco_nuvoloso);
if (LDati[0].nomeImg=="poco_nuvoloso_luna") tft.pushImage(0, 40, 72, 68, poco_nuvoloso_luna);
if (LDati[0].nomeImg=="stratificata2") tft.pushImage(0, 40, 72, 68, stratificata2);
//if (LDati[0].nomeImg=="velato stratificata2") tft.pushImage(0, 40, 72, 68, stratificata2);
if (LDati[0].nomeImg=="stratificata2_luna") tft.pushImage(0, 40, 72, 68, stratificata2_luna);
//if (LDati[0].nomeImg=="velato stratificata2_luna") tft.pushImage(0, 40, 72, 68, stratificata2_luna);
if (LDati[0].nomeImg=="temporale") tft.pushImage(0, 40, 72, 68, temporale);
if (LDati[0].nomeImg=="temporale_luna") tft.pushImage(0, 40, 72, 68, temporale);
if (LDati[0].nomeImg=="temporale_pom") tft.pushImage(0, 40, 72, 68, temporale_pom);
if (LDati[0].nomeImg=="temporale_pom_luna") tft.pushImage(0, 40, 72, 68, temporale_pom_luna);
if (LDati[0].nomeImg=="question") tft.pushImage(0, 40, 72, 68, question);
if (LDati[0].nomeImg=="") tft.pushImage(0, 40, 72, 68, question);
//descrizione meteo
//testoXY(90, 35, 1, ILI9341_WHITE, LD.desMeteo, false);
//Blynk.virtualWrite(FORECAST_CHAN, LD.desMeteo);
}
}
else
{
//ClearDisplay();
Serial.println("WiFi non connesso");
}
//DisplayData(dataOra);
}
dLAMMA ConvertiDatiLAMMA(String strDati)
{
//ritorna una struttura con i dati ricevuti dal LAMMA srv (TankPI)
dLAMMA LD;
int posiz=0;
String str="";
LD.desMeteo="";
LD.nomeImg="";
//estraggo i vari dati, data ultimo agg.to
posiz= strDati.indexOf(",");
if (posiz>0)
{
str= strDati.substring(0, posiz);
//LD.desMeteo= str;
//elimino il dato trovato
strDati.replace(str+",", "");
Serial.println("ult. agg.: "+str);
}
//descrizione meteo
posiz = strDati.indexOf(",");
if (posiz>0)
{
str= strDati.substring(0, posiz);
LD.desMeteo= str;
//elimino il dato trovato
strDati.replace(str+",", "");
Serial.println("descr. meteo: "+str);
}
//nome immagine da visualizzare
strDati.replace(".png", "");
strDati.replace("*", "");
LD.nomeImg= strDati;
Serial.println("nome immagine: "+strDati);
return LD;
}
bool IsWeather(const struct tm &timeinfo)
{ //ritorna true se l'orario casca all'inizio di una delle fasce previste per il cambio meteo
//le fasce sono:
//mattina: 8:00-10:59
//mattina2: 11:00-13:59
//pomeriggio: 14:00-16:59
//pomeriggio2: 17:00-19:59
//sera: 20:00-22:59
//sera2: 23:00-01:59
//notte 02:00-04:59
//Notte2 05:00-07:59
//
//converto la stringa dell'ora corrente in un intero e poi faccio i confronti.
int oraInt = 0;
String ora = ConvertiOra(timeinfo);
ora.replace(":", "");
oraInt = ora.toInt();
if ((oraInt >= 80000) && (oraInt <=105959)) currFascia = 1;
if ((oraInt >= 110000) && (oraInt <=135959)) currFascia = 2;
if ((oraInt >= 140000) && (oraInt <=165959)) currFascia = 3;
if ((oraInt >= 170000) && (oraInt <=195959)) currFascia = 4;
if ((oraInt >= 200000) && (oraInt <=225959)) currFascia = 5;
if ((oraInt >= 230000) && (oraInt <=235959)) currFascia = 6;
if ((oraInt >= 0) && (oraInt <=15959)) currFascia = 6;
if ((oraInt >= 20000) && (oraInt <=45959)) currFascia = 7;
if ((oraInt >= 50000) && (oraInt <=75959)) currFascia = 8;
if (currFascia != oldFascia)
{
//cambio fascia, deve richiedere nuovi dati
oldFascia=currFascia;
return true;
}
return false;
}