#include <Arduino.h>
// #include <WiFi.h> // Comentado temporalmente
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <U8g2lib.h>
// --- Datos WiFi ---
// const char* ssid = "TU_WIFI";
// const char* password = "TU_PASSWORD";
// --- Datos del tiempo ---
float temperatura = 0;
String estadoTiempo = "Desconocido";
float indiceUV = 0;
float volumenLluvia = 0;
float horasLluvia = 0;
float cloudCover = 0;
// --- Botón y pantalla ---
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);
int frame = 0;
#define PIN_BOTON 12
bool pantallaSecundaria = false;
unsigned long lastButtonPressTime = 0;
const unsigned long debounceDelay = 300;
// --- Temporizador de peticiones ---
unsigned long ultimaPeticion = 0;
const unsigned long intervaloPeticion = 600000; // 10 minutos en ms
void setup() {
Serial.begin(115200);
u8g2.begin();
pinMode(PIN_BOTON, INPUT_PULLUP);
// WiFi.begin(ssid, password); // Comentado temporalmente
// Serial.print("Conectando a WiFi");
// while (WiFi.status() != WL_CONNECTED) {
// delay(500);
// Serial.print(".");
// }
// Serial.println("\nWiFi conectado!");
pedirDatosDelTiempo(); // Primera llamada al inicio
}
void loop() {
unsigned long currentTime = millis();
// Lógica botón con debounce
if (digitalRead(PIN_BOTON) == LOW && (currentTime - lastButtonPressTime) > debounceDelay) {
lastButtonPressTime = currentTime;
pantallaSecundaria = !pantallaSecundaria;
}
// Actualizar datos cada 10 minutos
if (currentTime - ultimaPeticion > intervaloPeticion) {
ultimaPeticion = currentTime;
pedirDatosDelTiempo();
}
// Dibujar pantalla
u8g2.clearBuffer();
if (pantallaSecundaria) {
mostrarPantallaSecundaria();
} else {
mostrarPantallaPrincipal();
}
u8g2.sendBuffer();
frame += 6;
delay(100);
}
// === Función para obtener datos del tiempo ===
void pedirDatosDelTiempo() {
//if ((WiFi.status() == WL_CONNECTED)) {
HTTPClient http;
http.begin("https://api.open-meteo.com/v1/forecast?latitude=37.3222&longitude=-6.0586&daily=uv_index_max,precipitation_probability_max,precipitation_hours¤t=precipitation,temperature_2m,cloud_cover&timezone=auto&forecast_days=1");
int httpResponseCode = http.GET();
if (httpResponseCode == 200) {
String payload = http.getString();
Serial.println("JSON recibido:");
Serial.println(payload);
DynamicJsonDocument doc(2048);
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
temperatura = doc["current"]["temperature_2m"];
cloudCover = doc["current"]["cloud_cover"];
volumenLluvia = doc["current"]["precipitation"];
indiceUV = doc["daily"]["uv_index_max"][0];
float probLluvia = doc["daily"]["precipitation_probability_max"][0];
horasLluvia = doc["daily"]["precipitation_hours"][0];
// Lógica para determinar estado
if (probLluvia > 30) {
estadoTiempo = "Lluvia";
} else if (cloudCover > 60) {
estadoTiempo = "Nublado";
} else {
estadoTiempo = "Soleado";
}
} else {
Serial.print("Error al parsear JSON: ");
Serial.println(error.c_str());
}
} else {
Serial.print("Error en HTTP: ");
Serial.println(httpResponseCode);
}
http.end();
} //else {
//Serial.println("WiFi desconectado, intentando reconectar...");
//WiFi.reconnect();
//}
//}
// === Pantalla Principal ===
void mostrarPantallaPrincipal() {
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(0, 10, "Sevilla"); // Nombre fijo
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.drawStr(0, 25, ("Estado: " + estadoTiempo).c_str());
char buffer[32];
sprintf(buffer, "Temp: %.1f C", temperatura);
u8g2.drawStr(0, 38, buffer);
sprintf(buffer, "Clouds: %.1f %%", cloudCover);
u8g2.drawStr(0, 50, buffer);
sprintf(buffer, "Lluvia: %.1f mm", volumenLluvia);
u8g2.drawStr(0, 62, buffer);
// Animaciones
if (estadoTiempo == "Soleado") {
animacionSol(frame);
} else if (estadoTiempo == "Lluvia") {
animacionLluvia(frame);
} else if (estadoTiempo == "Nublado") {
animacionNube(frame);
}
}
// === Pantalla Secundaria ===
void mostrarPantallaSecundaria() {
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(0, 10, "Detalles del tiempo");
char buffer[32];
if (estadoTiempo == "Lluvia") {
sprintf(buffer, "Precip: %.1f mm", volumenLluvia);
u8g2.drawStr(0, 25, buffer);
sprintf(buffer, "Horas lluvia: %.1f", horasLluvia);
u8g2.drawStr(0, 38, buffer);
}
else if (estadoTiempo == "Soleado") {
sprintf(buffer, "Indice UV: %.1f", indiceUV);
u8g2.drawStr(0, 25, buffer);
u8g2.drawStr(0, 38, "Usar protector!");
}
if (estadoTiempo == "Soleado") {
animacionSol(frame);
} else if (estadoTiempo == "Lluvia") {
animacionLluvia(frame);
} else if (estadoTiempo == "Nublado") {
animacionNube(frame);
}
}
// === Animaciones ===
void animacionSol(int frame) {
int x = 100, y = 20, r = 8;
u8g2.drawCircle(x, y, r, U8G2_DRAW_ALL);
for (int i = 0; i < 8; i++) {
float angle = (frame + i * 45) * 3.14 / 180;
int x1 = x + cos(angle) * (r + 4);
int y1 = y + sin(angle) * (r + 4);
u8g2.drawPixel(x1, y1);
}
}
void animacionLluvia(int frame) {
int nubeX = 90, nubeY = 20;
u8g2.drawDisc(nubeX + 5, nubeY + 5, 6);
u8g2.drawDisc(nubeX + 14, nubeY + 3, 8);
u8g2.drawDisc(nubeX + 24, nubeY + 6, 6);
u8g2.drawBox(nubeX + 5, nubeY + 6, 19, 6);
for (int i = 0; i < 3; i++) {
int gotaX = nubeX + 8 + i * 6;
int gotaY = nubeY + 14 + ((frame + i * 10) % 30);
u8g2.drawPixel(gotaX, gotaY);
u8g2.drawPixel(gotaX, gotaY + 1);
}
}
void animacionNube(int frame) {
int nubeX = 95, nubeY = 20;
int offsetY = (sin(frame * 0.1) * 2);
u8g2.drawDisc(nubeX + 5, nubeY + 5 + offsetY, 6);
u8g2.drawDisc(nubeX + 14, nubeY + 3 + offsetY, 8);
u8g2.drawDisc(nubeX + 24, nubeY + 6 + offsetY, 6);
u8g2.drawBox(nubeX + 5, nubeY + 6 + offsetY, 19, 6);
}