#include <WiFi.h>
#include <time.h>
#include <ESP32Ping.h>
#include <iostream>
#include <string>
// #include <string.h>
#include <EEPROM.h>
#define EEPROM_SIZE 512
#define word_s unsigned short int
#define EE_HAY_DATOS (byte)0 // byte. 0xab si hay datos
#define EE_SSID_SIZE (byte)(EE_HAY_DATOS + sizeof(byte)) // byte. Total de bytes que ocupan las SSID con sus pass (incluye los 0 con los que terminan los strings)
#define EE_SSID_TOTAL (byte)(EE_SSID_SIZE + sizeof(byte)) // byte. Total de SSID con sus password guardados
#define EE_SSID_PREFERIDA (byte)(EE_SSID_TOTAL + sizeof(byte)) // byte. Numero de la SSID preferida para conectar
#define EE_SSID_GUARDADAS (byte)(EE_SSID_PREFERIDA + sizeof(byte)) // variable, tiene que estar al final. A partir de aca se guardan las SSID y sus password. Son stringz
// #define EE_TOTAL_VALORES (EE_SSID_PREFERIDA + sizeof(byte)) // byte, ojo, aca tengo que poner en sizeof, el tamaño de la linea anterior
#define WIFI_TIME_OUT_CONECTAR (word_s)10000 // 10 segundos
#define WIFI_TIME_OUT_INTERNET (word_s)10000 // 10 segundos
#define MAX_CANTIDAD_SSID (byte)5
#define WIFI_TIME_OUT_DATE_ERROR (word_s)30 * 1000
#define WIFI_TIME_OUT_DATE_NEXT (unsigned long)3600 * 1000
#define WIFI_AVISO_INTENTANDO (word_s)500 // indica que estoy intentando conectar
#define WIFI_TIME_TEST_HAY_INTERNET (word_s)30000 // 30". Cada este tiempo, verifico si hay Internet
#define WIFI_TIME_TEST_CORTO_HAY_INTERNET (word_s)10000
#define findeThisSSID(ii) ((byte)findSSID(ii, ii + 1,false))
#define findSSIDcircular(x,y) ((byte)findSSID(x, y,true))
#define hayInternet() flgHayInternet
// #define MAX_BYTES_SSID (byte)100
struct WifiCredentials
{
const char *ssid;
const char *pass;
};
// funciones
void printLocalTime(void);
bool verificarInternet(void);
bool estoyConectadoSSID(void);
byte findSSID(byte ssidInicial, byte ssidFinal, bool flgCircular = false);
void wifiIni(void);
bool updateDate(void);
word_s getByteEEPROM(byte posicion);
void getStringEEPROM(byte dondeInicia, byte *dondeGuardo);
bool conectarWifi(void);
void writeArrayEEPROM(void);
void writeStringToEEPROM(byte address, char * data);
bool findInList(String targetSSID, String ssidList[], int totalSSID);
void nextSSID(void);
// clases
class timer
{
private:
/* data */
public:
word_s time;
word_s timerEnd;
bool flgTimerIni;
bool flgTimerEnd;
timer(word_s _timerEnd);
~timer();
void reset(void);
bool pasoElTiempo(void);
};
timer::timer(word_s _timerEnd)
{
flgTimerIni = false;
flgTimerEnd = false;
timerEnd = _timerEnd;
}
timer::~timer()
{
}
void timer::reset(void)
{
flgTimerIni = false;
flgTimerEnd = false;
}
bool timer::pasoElTiempo(void)
{
if (flgTimerEnd)
{
return true;
}
if (flgTimerIni == false)
{
time = (word_s)millis(); // inicio timer
flgTimerIni = true; // timer iniciado
return false; // no paso el tiempo de espera
}
else
{
if ((word_s)((word_s)millis() - time) > (word_s)timerEnd)
{
flgTimerIni = false; // reseteo el timer
flgTimerEnd = true; // no cuento mas
return true; // paso el tiempo de espera
}
else
{
return false; // no paso el tiempo de espera
}
}
}
// variables
// const char *ssid = "HT";
// const char *password = "ElGlobito1973Me";
// bool flgSSIDencontrada = false;
// bool flgHoraActualizada = false;
// bool flgWifiSSIDok;
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = -3 * 3600; // Ajusta esta variable a tu huso horario (en segundos)
const int daylightOffset_sec = 0; // Ajusta esta variable si tu región tiene horario de verano (en segundos)
const IPAddress remote_ip(8, 8, 8, 8);
bool flgHayInternet = false;
bool flgWiFiSSIDfound = false;
bool flgWiFiconectado = false;
bool flgEEPROMbegin = false;
bool flgDateOK = false;
byte ssidPreferida;
byte totalSSID;
WifiCredentials arrayWifiCredentials[MAX_CANTIDAD_SSID];
WifiCredentials ht_wifi_credentials = {
.ssid = "HT",
.pass = "ElGlobito1973Me"
};
timer conectoSSID(WIFI_TIME_OUT_CONECTAR);
timer timeOutInternet(WIFI_TIME_OUT_INTERNET);
timer timerPing((word_s)0);
void codigoGeneral(void)
{
}
void setup()
{
Serial.begin(57600);
Serial.println("Iniciado");
writeArrayEEPROM();
wifiIni(); // inicio el Wifi
for (;;) {
loop();
}
/*
Serial.begin(57600);
writeArrayEEPROM();
wifiIni(); // inicio el Wifi
// conectoSSID = timer(WIFI_TIME_OUT_CONECTAR);
// timeOutInternet = timer(WIFI_TIME_OUT_INTERNET);
byte bb = findSSID(ssidPreferida, totalSSID, true);
//byte bb=findeThisSSID(3);
Serial.println(bb == 0xff ? "No encontre SSID valida" : "Encontre una SSID valida: " + String(bb));
for (;;);
while (true) {
conectarWifi();
}
for (;;);
Serial.println("Try");
findeThisSSID(ssidPreferida);
if (flgWiFiSSIDfound) {
Serial.println("Found");
while (estoyConectadoSSID() == false) {
Serial.print('.');
delay(100);
}
}
else {
Serial.println("No esta la SSID");
for (;;);
}
Serial.println("");
Serial.println("hayInternet()");
for (;;) {
hayInternet();
}
*/
}
void loop()
{
if (flgWiFiSSIDfound == true)
{
if (estoyConectadoSSID())
{
Serial.println("Estoy conectado");
if (hayInternet() == false)
{
if (timeOutInternet.pasoElTiempo())
{
Serial.println("Paso el tiempo de espera para tener Internet");
nextSSID();
}
else
{
Serial.println("No paso el tiempo de espera para tener Internet");
}
}
else
{
timeOutInternet.reset(); // reseteo el timer
}
verificarInternet();
}
else
{
Serial.println("No estoy conectado");
if (conectoSSID.pasoElTiempo())
{
Serial.println("Paso el tiempo de espera para conectar");
nextSSID();
}
else
{
Serial.println("No paso el tiempo de espera para conectar");
}
}
}
else
{
findSSID(ssidPreferida, totalSSID, true); // busco una SSID. Reseteo los timers. Busco todas empezando por la preferida.
}
codigoGeneral();
return;
/*
if (hayInternet() == false)
{
Serial.println("No hay Internet");
if (haySSIDdisponible())
{
Serial.println("Hay SSID disponible");
if (estoyConectadoSSID())
{
Serial.println("Estoy conectado");
if (timeOutInternet.pasoElTiempo())
{
Serial.println("Paso el tiempo de espera para tener Internet");
nextSSID();
}
else
{
Serial.println("No paso el tiempo de espera para tener Internet");
}
}
else
{
Serial.println("No estoy conectado");
if (conectoSSID.pasoElTiempo())
{
Serial.println("Paso el tiempo de espera para conectar");
nextSSID();
}
else
{
Serial.println("No paso el tiempo de espera para conectar");
}
}
}
else
{
Serial.println("No hay SSID disponible");
findSSID(ssidPreferida, totalSSID, true);
conectoSSID.reset(); // reseteo el timer
}
}
else
{
Serial.println("Hay Internet");
timeOutInternet.reset(); // reseteo el timer
}
verificarInternet();
codigoGeneral();
*/
}
word_s getByteEEPROM(byte posicion)
{
byte byteEnEEPROM;
EEPROM.get(posicion, byteEnEEPROM);
return byteEnEEPROM;
}
void getStringEEPROM(byte dondeInicia, byte *dondeGuardo)
{
/*
obtengo strings terminados en 0 de la EEPROM de la posicion dondeInicia y los guardo en el string dondeGuardo
*/
byte byteLeido, ii;
// Serial.println("getStringEEPROM()");
// Serial.println("dondeInicia: "+String(dondeInicia));
// for(;;);
byteLeido = 255;
for (ii = 0; byteLeido != 0; ++ii)
{
// byteLeido = getByteEEPROM(dondeInicia + ii);
byteLeido = EEPROM.read((byte)(dondeInicia + ii));
dondeGuardo[ii] = byteLeido;
// Serial.println(byteLeido);
// *(dondeGuardo + ii) = byteLeido;
}
*(dondeGuardo + ii) = 0;
}
void wifiIni(void)
{
/*
Cargo los SSID/pass si los hubiera desde ROM.
Cargo el Wifi de HT
Cargo la SSID favorita si la hubiera, si no, la de HT.
EE_HAY_DATOS == 0xab -> hay datos en EEPROM
*/
byte *ptrSSIDdata;
byte sizeString;
byte posicionEEPROM;
byte hayDatos;
byte size;
Serial.println("wifiIni()");
if (flgEEPROMbegin == false)
{
// EEPROM.begin(EE_TOTAL_VALORES);
EEPROM.begin(EEPROM_SIZE);
flgEEPROMbegin = true;
}
//hayDatos = getByteEEPROM(EE_HAY_DATOS);
hayDatos = EEPROM.read((byte)EE_HAY_DATOS);
totalSSID = 0;
if (hayDatos == 0xab)
{ // hay datos grabados en flash?
// Serial.print("hay datos: ");
totalSSID = EEPROM.read((byte)EE_SSID_TOTAL);
//totalSSID = getByteEEPROM(EE_SSID_TOTAL); // cuando grabo la EEPROM, tengo que darle 0 o el total de las SSID.
size = EEPROM.read((byte)EE_SSID_SIZE);
//EEPROM.get(EE_SSID_SIZE, size);
ptrSSIDdata = new byte[size]; // creo suficiente memoria para cargar los SSID/Pass que estan en EEPROM
// ptrSSIDdata = new byte[getByteEEPROM(EE_SSID_SIZE)]; // creo suficiente memoria para cargar los SSID/Pass que estan en EEPROM
posicionEEPROM = EE_SSID_GUARDADAS;
// ptrSSIDdata = 0;
// cargo en memoria los SSID/Pass que estan en EEPROM
if (totalSSID > 0)
{
for (byte ii = 0; ii < totalSSID; ++ii)
{
getStringEEPROM(posicionEEPROM, ptrSSIDdata);
arrayWifiCredentials[ii + 1].ssid = (char *)ptrSSIDdata;
sizeString = strlen((char *)ptrSSIDdata) + 1;
posicionEEPROM += sizeString;
ptrSSIDdata += sizeString;
getStringEEPROM(posicionEEPROM, ptrSSIDdata);
arrayWifiCredentials[ii + 1].pass = (char *)ptrSSIDdata;
sizeString = strlen((char *)ptrSSIDdata) + 1;
posicionEEPROM += sizeString;
ptrSSIDdata += sizeString;
}
}
ssidPreferida = EEPROM.get(EE_SSID_PREFERIDA, ssidPreferida);
//EEPROM.read((byte)EE_SSID_PREFERIDA)
// ssidPreferida = getByteEEPROM(EE_SSID_PREFERIDA);
} else {
ssidPreferida = 0; // favorita es la de HT (no hay datos en EEPROM)
/*
Serial.print("No hay datos: ");
Serial.println(hayDatos);
*/
}
arrayWifiCredentials[0] = ht_wifi_credentials; // cargo la de la fabrica
++totalSSID;
flgHayInternet = false;
flgWiFiSSIDfound = false;
flgWiFiconectado = false;
/*
Serial.print("totalSSID:");
Serial.println(totalSSID);
Serial.print("ssidPreferida:");
Serial.println(ssidPreferida);
Serial.println(arrayWifiCredentials[ssidPreferida].ssid);
Serial.println(arrayWifiCredentials[ssidPreferida].pass);
Serial.print("size:");
Serial.println(size);
for(int ii=0;ii < totalSSID;++ii){
Serial.println(arrayWifiCredentials[ii].ssid);
Serial.println(arrayWifiCredentials[ii].pass);
}
*/
}
/*
bool conectarWifi(void)
{
static bool flgTimerConectarWiFi;
static word_s timerConectarWiFi;
static bool flgTimerTenerInternet;
static word_s timerTenerInternet;
static bool flgAvisoIntentandoIni;
bool flgNoBusquePreferida;
static word_s timerAvisoIntentando;
byte startSSID;
startSSID = 0;
flgNoBusquePreferida = false;
Serial.println("conectarWifi()");
if (flgWiFiSSIDfound == true && (flgWiFiconectado == false || flgHayInternet == false)) // encontre la SSID pero todavia no me conecte o me conecte y no tengo Internet
{
Serial.println("encontre la SSID pero todavia no me conecte o me conecte y no tengo Internet");
if (((word_s)millis() - timerConectarWiFi > WIFI_TIME_OUT_CONECTAR && (flgWiFiconectado == false)) || (((word_s)millis() - timerTenerInternet > WIFI_TIME_OUT_INTERNET) && (flgHayInternet == false))) // el tiempo paso y no me pude conectar o no tengo internet?
{
Serial.println("desconecto");
if (((word_s)millis() - timerConectarWiFi > WIFI_TIME_OUT_CONECTAR && (flgWiFiconectado == false))) {
Serial.println("1");
}
if ((((word_s)millis() - timerTenerInternet > WIFI_TIME_OUT_INTERNET) && (flgHayInternet == false))) {
Serial.println("2");
}
WiFi.disconnect(); // desconecto la red
flgTimerConectarWiFi = false; // reseteo el timer
flgTimerTenerInternet = false; // reseteo el timer
flgNoBusquePreferida = true; // no busque la preferida
flgAvisoIntentandoIni = false; // reseteo el timer
if (ssidPreferida == (totalSSID - 1))
{ // ya no puedo incrementar?
startSSID = 0; // arranque desde el principio
}
else
{
startSSID++;
}
}
else
{
// no paso el tiempo
if (flgAvisoIntentandoIni == false)
{
Serial.println("inicio timer indicador de intentando conectar");
timerAvisoIntentando = (word_s)millis(); // inicio timer indicador de intentando conectar
flgAvisoIntentandoIni = true;
}
else
{
Serial.println("(word_s)millis() - timerAvisoIntentando > WIFI_AVISO_INTENTANDO");
if ((word_s)millis() - timerAvisoIntentando > WIFI_AVISO_INTENTANDO)
{
flgAvisoIntentandoIni = false; // reseteo el timer
Serial.print('.');
}
}
return false; // no me conecte todavia
}
}
// Serial.println("no encontre la SSID");
flgWiFiSSIDfound = false; // no encontre SSID
// si no hay una preferida, cuando grabo EEPROM tengo que poner 0 que es HT
if (ssidPreferida != 0) // hay una SSID preferida?
{
Serial.println("hay una SSID preferida");
findeThisSSID(ssidPreferida);
}
if (flgWiFiSSIDfound == false) // no encontre la SSID
{
// trato de conectar a cualquier SSID
Serial.println("trato de conectar a cualquier SSID");
ssidPreferida = findSSID(startSSID, totalSSID);
}
if (flgWiFiSSIDfound == false) // no encontre la SSID
{
Serial.println("reseteo el timer");
flgAvisoIntentandoIni = false; // reseteo el timer
return false; // no hay ninguna
}
// encontre una SSID valida
if (estoyConectadoSSID())
{
Serial.println("Conectado a WiFi");
if (hayInternet())
{
Serial.println("Hay Internet");
updateDate();
return true;
}
else
{
// estoy conectado, pero no tengo internet
Serial.println("estoy conectado, pero no tengo internet");
if (flgTimerTenerInternet == false) // no inicie el timer de time out conectando a WiFi ?
{
timerTenerInternet = (word_s)millis();
flgTimerTenerInternet = true; // inicio el timer
}
return false; // no me conecte todavia
}
}
else
{
// encontre una SSID pero todavia no me conecte
Serial.println("encontre una SSID pero todavia no me conecte");
if (flgTimerConectarWiFi == false) // no inicie el timer de time out conectando a WiFi ?
{
Serial.println("inicio el timer");
timerConectarWiFi = (word_s)millis();
flgTimerConectarWiFi = true; // inicio el timer
}
return false; // no me conecte todaviaF
}
}
*/
bool updateDate(void)
{
static bool flgUpdateDateIni = false;
static unsigned long timerUpdateDate;
static unsigned long timeOtroIntento;
struct tm timeinfo;
if (flgUpdateDateIni == false) // no inicie el timer de time out conectando a WiFi ?
{
timerUpdateDate = millis();
flgUpdateDateIni = true; // inicio el timer
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); // Configurar el RTC con el servidor NTP
if (!getLocalTime(&timeinfo)) // error obteniendo el tiempo?
{
timeOtroIntento = WIFI_TIME_OUT_DATE_ERROR;
flgDateOK = false; // error actualizando la fecha
return false; // los datos recibidos no fueron validos
}
else
{
printLocalTime();
timeOtroIntento = WIFI_TIME_OUT_DATE_NEXT;
flgDateOK = true;
return true;
}
}
else
{
// inicie el timer
if (millis() - timerUpdateDate > timeOtroIntento)
{
flgUpdateDateIni = false; // es hora de intentar actualizar nuevamente
}
return false; // no me conecte todavia
}
}
byte actualSSID;
byte findSSID(byte ssidInicial, byte ssidFinal, bool flgCircular)
{
// Start WiFi scan
int n = WiFi.scanNetworks();
String ssidList[n];
Serial.println("findSSID(" + String(ssidInicial) + "," + String(ssidFinal) + "," + String(flgCircular) + ")");
// Store SSIDs in lowercase
for (int i = 0; i < n; ++i)
{
ssidList[i] = WiFi.SSID(i);
}
for (byte ii = ssidInicial; ii < ssidFinal; ++ii)
{
if (findInList(String(arrayWifiCredentials[ii].ssid), ssidList, n) == true)
{
WiFi.begin(arrayWifiCredentials[ii].ssid, arrayWifiCredentials[ii].pass);
flgWiFiSSIDfound = true; // encontre la SSID
Serial.println("OK: " + String(arrayWifiCredentials[ii].ssid));
actualSSID = ii;
conectoSSID.reset(); // reseteo el timer
return ii; // encontre una SSID valida
}
else
{
Serial.println("No: " + String(arrayWifiCredentials[ii].ssid));
continue;
}
}
if (flgCircular == false || ssidInicial == 0)
{
flgWiFiSSIDfound = false; // no encontre la SSID
actualSSID = 0xff;
return 0xff; // no esta la SSID
}
else
{
Serial.println("Circular");
return findSSID(0, ssidInicial, false);
}
}
bool findInList(String targetSSID, String ssidList[], int totalSSID)
{
// Check if target SSID is in the list
for (int i = 0; i < totalSSID; ++i)
{
if (ssidList[i] == targetSSID)
{
return true;
}
}
return false;
}
void nextSSID(void)
{
if (actualSSID != 0xff && totalSSID > 0)
{
if (actualSSID < (totalSSID - 1))
{
findSSID(actualSSID + 1, totalSSID, true);
}
else
{
findSSID(0, actualSSID, false); // es la ultima, vuelve a la primera
}
}
}
bool verificarInternet(void)
{
if (timerPing.pasoElTiempo())
{
// Realiza un ping al servidor DNS de Google (8.8.8.8)
if (Ping.ping(remote_ip, 1))
{
Serial.println("Hay Internet");
flgHayInternet = true;
}
else
{
Serial.println("No hay Internet");
flgHayInternet = false;
}
if (flgHayInternet == false) { // no tengo internet?
timerPing.timerEnd = WIFI_TIME_TEST_CORTO_HAY_INTERNET;
} else {
timerPing.timerEnd = WIFI_TIME_TEST_HAY_INTERNET;
}
timerPing.reset();
Serial.print("Ping: ");
Serial.println(flgHayInternet ? "Si" : "No");
} else {
Serial.println((word_s)timerPing.timerEnd - ((word_s)((word_s)millis() - (word_s)timerPing.time)));
}
// Serial.println(flgHayInternet ? "Si" : "No");
return flgHayInternet;
}
bool estoyConectadoSSID(void)
{
if (WiFi.status() == WL_CONNECTED)
{
if (flgWiFiconectado == false) { // vengo de no estar conectado y ahora estoy conectado?
timerPing.timerEnd = (word_s)0; // Reseteo el timer de verificar Internet. Inmediatamente
timerPing.reset();
timeOutInternet.reset(); // reseteo el timer de time out buscando Internet.
flgHayInternet = false;
}
flgWiFiconectado = true;
return true;
} else { // no estoy conectado
if (flgWiFiconectado == true) { // vengo de estar conectado y ahora no estoy conectado?
conectoSSID.timerEnd = (word_s)0; // Reseteo el timer de time out conexion. Inmediatamente
conectoSSID.reset();
flgHayInternet = false;
}
flgWiFiconectado = false;
return false;
}
}
void printLocalTime()
{
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
Serial.println("Error al obtener la hora");
return;
}
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}
const char *ssdi1 = "Wokwi-GUEST";
const char *pass1 = "";
const char *ssdi2 = "HTFULL";
const char *pass2 = "PASS3";
const char *ssdi3 = "FUENTESDEENERGIA";
const char *pass3 = "PASS2";
void writeArrayEEPROM(void)
{
/*
Guardo en la EEPROM los valores de totalSSID, ssidPreferida y los SSID/Pass guardados en el array
*/
// return;
byte ptr;
EEPROM.begin(EEPROM_SIZE);
EEPROM.put((byte)EE_HAY_DATOS, 0xab); // hay datos
EEPROM.put((byte)EE_SSID_TOTAL, 3);
EEPROM.put((byte)EE_SSID_PREFERIDA, 2);
ptr = (byte)EE_SSID_GUARDADAS;
writeStringToEEPROM(ptr, ssdi1);
// EEPROM.put(ptr, ssdi1);
ptr += (strlen(ssdi1) + 1);
writeStringToEEPROM(ptr, pass1);
// EEPROM.put(ptr, pass1);
ptr += (strlen(pass1) + 1);
// EEPROM.put(ptr, ssdi2);
writeStringToEEPROM(ptr, ssdi2);
ptr += (strlen(ssdi2) + 1);
writeStringToEEPROM(ptr, pass2);
// EEPROM.put(ptr, pass2);
ptr += (strlen(pass2) + 1);
// EEPROM.put(ptr, ssdi3);
writeStringToEEPROM(ptr, ssdi3);
ptr += (strlen(ssdi3) + 1);
// EEPROM.put(ptr, pass3);
writeStringToEEPROM(ptr, pass3);
ptr += (strlen(pass3) + 1);
EEPROM.put((byte)EE_SSID_SIZE, (byte)(ptr - EE_SSID_GUARDADAS));
EEPROM.commit();
/*
Serial.println("EE_HAY_DATOS: "+ String(EEPROM.read((byte)EE_HAY_DATOS)));
Serial.println("EE_SSID_TOTAL: "+ String(EEPROM.read((byte)EE_SSID_TOTAL)));
Serial.println("EE_SSID_PREFERIDA: "+ String(EEPROM.read((byte)EE_SSID_PREFERIDA)));
Serial.println("EE_SSID_SIZE: "+ String(EEPROM.read((byte)EE_SSID_SIZE)));
*/
flgEEPROMbegin = true;
/*
for(int ii=0;ii < totalSSID;++ii){
Serial.println(arrayWifiCredentials[ii + 1].ssid);
Serial.println(arrayWifiCredentials[ii + 1].pass);
}
for(;;);
*/
}
void writeStringToEEPROM(byte address, const char * data) {
byte size;
size = strlen(data);
for (byte i = 0; i < size + 1; i++) {
EEPROM.write(address + i, data[i]);
}
EEPROM.commit();
}