#include #include #include #include #include #include #include #include #include #include #include #include ADC_MODE(ADC_VCC); //############################################################################################# //Configuracion global // WiFi const char* ssid_wifi = "xxxxxxxxxxxxxx"; // ssid const char* password_wifi = "xxxxxxxxxxxxxx"; // password const char* ssid2_wifi = "xxxxxxxxxxxxxx"; const char* password2_wifi = "xxxxxxxxxxxxxx"; const char* ssid3_wifi = "xxxxxxxxxxxxxx"; const char* password3_wifi = "xxxxxxxxxxxxxx"; String password_wifi_seleccionado; String ssid_wifi_seleccionado; IPAddress ip(192, 168, 1, 71); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); IPAddress dns(8, 8, 8, 8); // MQTT String mqtt_server_1 = "192.168.1.XXX"; int BROKER_PORT_1 = 1883; String mqtt_server_2 = "xxxxxxxxxxxxxx.duckdns.org"; int BROKER_PORT_2 = 1883; String mqtt_server_sel = mqtt_server_1; int BROKER_PORT = BROKER_PORT_1; const char* mqtt_user_sel = "xxxxxxxxxxxxxx"; const char* mqtt_password_sel = "xxxxxxxxxxxxxx"; //############################################################################################# String MQTT_HOST = "multi_tracker"; //Led de estado cada tres segundos boolean led_status = true; long lastMsg = 0; boolean inicial = true; long nvecesbucle = 0; long bucleEncendido = 20000; long bucleApagado = 1000; boolean led_encendido = false; long lastReconnectAttempt = 0; byte nIP = 0; int respuesta_ping[256]; long ultima_llamada_ping[256]; byte nCiclo = 0; float segundos; //delay entre llamadas si ha contestado anteriormente delay_off a 0 hace llamadas constantes , si no valor en milisegundos long delay_off = ( 5 * 60 * 1000 ); //############################################################################################# #define ESP_getChipId() (ESP.getChipId()) #define LED_ON LOW #define LED_OFF HIGH String ssid = "Tracker_" + String(ESP_getChipId(), HEX); const char* password = "1234"; WiFiClient WirelessClient; PubSubClient mqttClient(WirelessClient); //############################################################################################# const int resetButton = 16; boolean saveConfigs = false; //############################################################################################# byte ip_prioritarias_1[][4] = { { 192, 168, 1, 21 } , { 192, 168, 1, 24 } , { 192, 168, 1, 28 } }; byte ip_prioritarias_2[][4] = { { 192, 168, 3, 1 } , { 192, 168, 3, 101 } , { 192, 168, 3, 140 } }; byte ip_prioritarias[][4] = { { 192, 168, 1, 21 } , { 192, 168, 1, 24 } , { 192, 168, 1, 28 } }; //############################################################################################# // MQTT: topic String reconexion_topic = MQTT_HOST + "/reconexion"; String MQTT_IP_STATUS_TOPIC = MQTT_HOST + "/IP_"; String MQTT_RESTART_TOPIC = MQTT_HOST + "/restart"; String MQTT_ALL_DEVICES_TOPIC = MQTT_HOST + "/all_devices"; // default payload char* STATUS_ON = "1"; char* STATUS_OFF = "0"; char* SWITCH_ON = "1"; char* SWITCH_OFF = "0"; const byte IP_MODE_ALL = 1; const byte IP_MODE_ONLY_ACTIVE = 2; const byte IP_MODE_ONLY_KNOWN = 3; const byte IP_MODE_ALTERNATE = 4; byte ip_mode; //############################################################################################# const char* remote_host = "www.google.com"; int contador = 0; int ncaracter = 0; //############################################################################################# #define DRD_TIMEOUT 1.0 #define DRD_ADDRESS 0x00 DoubleResetDetect drd(DRD_TIMEOUT, DRD_ADDRESS); void getBarsSignal(long rssi) { // 5. High quality: 90% ~= -55db // 4. Good quality: 75% ~= -65db // 3. Medium quality: 50% ~= -75db // 2. Low quality: 30% ~= -85db // 1. Unusable quality: 8% ~= -96db // 0. No signal int bars; if (rssi > -55) { Serial.print("Nivel de señal : "); Serial.println("Alta calidad > -55dBm"); } else if (rssi < -55 & rssi > -65) { Serial.print("Nivel de señal : "); Serial.println("Buena calidad > -65dBm"); } else if (rssi < -65 & rssi > -75) { Serial.print("Nivel de señal : "); Serial.println("Calidad media > -75dBm"); } else if (rssi < -75 & rssi > -85) { Serial.print("Nivel de señal : "); Serial.println("Calidad baja > -85dBm"); } else if (rssi < -85 & rssi > -96) { Serial.print("Nivel de señal : "); Serial.println("Muy bajo o imposible de conectar > -96dBm"); } else { Serial.print("Nivel de señal : "); Serial.println("SIN SEÑAL"); } } String printDigits(int digits) { String Salida = ""; if (digits < 10) Salida = '0'; Salida += String(digits); return Salida; } void reiniciar_esp() { Serial.println("#####################################################"); Serial.println("MQTT RECIBIDO : COMANDO /RESTART"); Serial.println("#####################################################"); ESP.restart() ; } boolean tiempo_entre_llamadas(long ultima_llamada){ //Devuelve true si ha pasado mas tiempo desde la ultima llamada y el tiempo de delay que el tiempo actual , o si estaba a cero ( sin inicializar ) boolean resultado = true; long ahora = millis(); float segundos; if ( delay_off == 0 ){ resultado = true; } else{ if (ultima_llamada != 0){ if ( ahora > ( ultima_llamada + delay_off ) ){ resultado = true; } else{ resultado = false; // segundos = (( ultima_llamada + delay_off ) - ahora ); // Serial.print(" , *** Omitida *** siguiente ciclo en : "); // Serial.print(segundos/1000); // Serial.println(" Segs."); } } else{ resultado = true; } } return resultado; } void setup() { byte i; ip_mode = IP_MODE_ONLY_KNOWN; byte mac[6]; unsigned long startedAt = millis(); randomSeed(micros()); //reset settings - for testing // wifiManager.resetSettings(); Serial.begin(115200); delay(10); Serial.println(""); Serial.println(""); Serial.println(""); Serial.println(""); Serial.println(""); Serial.println(""); Serial.println("#################################"); Serial.print("Motivo ultimo reset : "); Serial.println(ESP.getResetReason()); Serial.print("ID Chip : "); Serial.println(ESP.getChipId()); float voltaje=0.00f; voltaje = ESP.getVcc(); Serial.print("Tensión alimentación : "); Serial.print(voltaje/1024.00f); Serial.println(" V"); if (drd.detect()) { Serial.println("** Double reset boot **"); Serial.println("#################################"); Serial.println("Llamando a la configuracion del portal cautivo"); Serial.println("#################################"); ESP.restart() ; } else { Serial.println("** Normal boot **"); Serial.println("#################################"); SPIFFS.begin(); pinMode(BUILTIN_LED, OUTPUT); // BUILTIN_LED pin como salida D4 digitalWrite(BUILTIN_LED, false); delay(10); Serial.println(); Serial.println("Conectando a la red WiFi"); // scan.... int n = WiFi.scanNetworks(); for (int i = 0; i < n; ++i) { Serial.println(WiFi.SSID(i)); if (WiFi.SSID(i) == ssid_wifi ) { WiFi.config(ip, dns , gateway, subnet); WiFi.begin(ssid_wifi, password_wifi); // xxxxxxxxxxxxxx password_wifi_seleccionado = password_wifi; ssid_wifi_seleccionado = ssid_wifi; break; } if (WiFi.SSID(i) == ssid2_wifi) { WiFi.begin(ssid2_wifi, password2_wifi); // xxxxxxxxxxxxxx password_wifi_seleccionado = password2_wifi; ssid_wifi_seleccionado = ssid2_wifi; break; } if (WiFi.SSID(i) == ssid3_wifi) { WiFi.begin(ssid3_wifi, password3_wifi); // xxxxxxxxxxxxxx password_wifi_seleccionado = password3_wifi; ssid_wifi_seleccionado = ssid3_wifi; break; } } // Conectar a wifi contador = 1; Serial.print(printDigits(contador)); while (WiFi.status() != WL_CONNECTED) { delay(40); Serial.print("."); digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED)); ncaracter++; if (ncaracter >= 25) { Serial.println(""); contador++; Serial.print(printDigits(contador)); ncaracter = 0; } if (contador >= 100) { Serial.println("#####################################################"); Serial.println("REINICIANDO DISPOSITIVO POR NO CONECTAR A LA RED WIFI"); Serial.println("#####################################################"); ESP.restart() ; } } Serial.println(""); //Esta conectado por lo que entramos en el bucle de control de conexion Serial.println("#################################"); Serial.print("Conectado WiFi a : "); Serial.println(WiFi.SSID()); Serial.print("Direccion IP : "); Serial.println(WiFi.localIP()); Serial.print("Mascara : "); Serial.println(WiFi.subnetMask()); Serial.print("Puerta de enlace : "); Serial.println(WiFi.gatewayIP()); Serial.print("MAC Wifi : "); Serial.println(WiFi.macAddress()); long rssi = WiFi.RSSI(); Serial.print("Nivel de señal : "); Serial.print(rssi); Serial.println("dBm"); getBarsSignal(rssi); // Servidor MQTT Serial.println("#################################"); Serial.print("Configurando servidor MQTT : "); Serial.println(WiFi.SSID()); if (WiFi.SSID() == ssid_wifi ) { // xxxxxxxxxxxxxx mqtt_server_sel = mqtt_server_1; BROKER_PORT = BROKER_PORT_1; memcpy(ip_prioritarias, ip_prioritarias_1, sizeof ip_prioritarias_1); } if (WiFi.SSID() == ssid2_wifi) { // xxxxxxxxxxxxxx mqtt_server_sel = mqtt_server_2; BROKER_PORT = BROKER_PORT_2; memcpy(ip_prioritarias, ip_prioritarias_2, sizeof ip_prioritarias_2); } if (WiFi.SSID() == ssid3_wifi) { // xxxxxxxxxxxxxx mqtt_server_sel = mqtt_server_2; BROKER_PORT = BROKER_PORT_2; memcpy(ip_prioritarias, ip_prioritarias_1, sizeof ip_prioritarias_1); } Serial.print("Conectando a servidor MQTT : "); Serial.println(mqtt_server_sel); Serial.print("Usuario servidor MQTT : "); Serial.println(mqtt_user_sel); // Cliente MQTT mqttClient.setServer((char*) mqtt_server_sel.c_str(), BROKER_PORT); mqttClient.setCallback(callback); lastReconnectAttempt = 0; mqttClient.publish((char*) reconexion_topic.c_str() , "OK"); Serial.println("#################################"); ArduinoOTA.begin(); nCiclo = 0; } } void mqtt_all_devices() { IPAddress ip_ping = WiFi.localIP(); String json; DynamicJsonDocument doc(16 * 1024); for (nIP = 1; nIP <= 255; nIP++) { ip_ping[3] = nIP; if (respuesta_ping[nIP] > 0 ) { doc[ipToString(ip_ping)] = "1"; } else { doc[ipToString(ip_ping)] = "0"; } } serializeJson(doc, json); if (mqttClient.connected()) { // Serial.println("MQTT OK"); } else { Serial.println("SIN CONEXION AL SERVIDOR MQTT"); boolean rc = reconnect(); } Serial.println(json); mqttClient.publish((char*) MQTT_ALL_DEVICES_TOPIC.c_str() , (char*) json.c_str()); } void callback(char* p_topic, byte* p_payload, unsigned int p_length) { String payload; for (uint8_t i = 0; i < p_length; i++) { payload.concat((char)p_payload[i]); } Serial.print("Topic recibido : "); Serial.println(String(p_topic)); Serial.print("Payload recibido : "); Serial.println(String(payload)); // handle message topic if (MQTT_RESTART_TOPIC.equals(String(p_topic))) { Serial.print("Topic recibido RESTART : "); Serial.println(String(p_topic)); reiniciar_esp(); } if (MQTT_ALL_DEVICES_TOPIC.equals(String(p_topic))) { Serial.print("Topic recibido ALL DEVICES : "); Serial.println(String(p_topic)); mqtt_all_devices(); } } boolean reconnect() { // Loop until we're reconnected while (!mqttClient.connected()) { Serial.println("Reintentando conexión MQTT ..."); // Attempt to connect // Create a random client ID String clientId = "ESP8266Client-"; clientId += String(random(0xffff), HEX); if (mqttClient.connect(clientId.c_str(), mqtt_user_sel, mqtt_password_sel)) { Serial.println("MQTT Conectado ..."); // Once connected, publish an announcement... mqttClient.publish((char*) reconexion_topic.c_str() , "OK"); // ... and resubscribe } return mqttClient.connected(); } } void publishSwitchState_IP(String IP , boolean lEstado) { String topic = MQTT_IP_STATUS_TOPIC + IP + "/status"; if (mqttClient.connected()) { // Serial.println("MQTT OK"); } else { Serial.println("SIN CONEXION AL SERVIDOR MQTT"); boolean rc = reconnect(); } // Serial.print("Enviado Topic : "); // Serial.print(topic); // Serial.print(",Estado : "); if ( lEstado == false ) { mqttClient.publish((char*) topic.c_str() , "0"); // Serial.println(String(STATUS_OFF)); } else { mqttClient.publish((char*) topic.c_str() , "1"); // Serial.println(String(STATUS_ON)); } } void ping_alternate(byte IP_ini , byte IP_fin ) { IPAddress ip_ping = WiFi.localIP(); const byte peticiones_ping = 1; Serial.println("----> Ip rango a comprobar : "); for (nIP = IP_ini; nIP <= IP_fin; nIP++) { Serial.print(" - "); Serial.print(ip_ping); if ((tiempo_entre_llamadas(ultima_llamada_ping[nIP]) == true) || ( respuesta_ping[nIP] == 0)){ ip_ping[3] = nIP; if (Ping.ping(ip_ping, peticiones_ping)) { // Serial.println("Contesta ... "); int avg_time_ms = Ping.averageTime(); respuesta_ping[nIP] = avg_time_ms; Serial.print(" , Tiempo respuesta : "); Serial.print(avg_time_ms); Serial.print(" ms"); // Serial.println("-----------------------"); // Serial.println(nIP); // Serial.println(respuesta_ping[nIP]); // Serial.println("-----------------------"); publishSwitchState_IP(ipToString(ip_ping), true); } else { respuesta_ping[nIP] = 0; ultima_llamada_ping[nIP] = 0; Serial.print(" , Error : No contesta"); publishSwitchState_IP(ipToString(ip_ping), false); } Serial.println(""); ultima_llamada_ping[nIP] = millis(); } else{ Serial.print(" *** Ip omitida *** por delay_off"); segundos = (( ultima_llamada_ping[nIP] + delay_off ) - millis() ); Serial.print(" , siguiente ciclo en : "); Serial.print(segundos/1000); Serial.println(" Segs."); } digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED)); } digitalWrite(BUILTIN_LED, false ); } void ping_all_netwotk() { IPAddress ip_ping = WiFi.localIP(); const byte peticiones_ping = 1; Serial.println("----> Ip comprobar toda la red : "); for (nIP = 1; nIP <= 255; nIP++) { ip_ping[3] = nIP; Serial.print(" - "); Serial.print(ip_ping); if ((tiempo_entre_llamadas(ultima_llamada_ping[nIP]) == true) || ( respuesta_ping[nIP] == 0)){ if (Ping.ping(ip_ping, peticiones_ping)) { // Serial.println("Contesta ... "); int avg_time_ms = Ping.averageTime(); respuesta_ping[nIP] = avg_time_ms; Serial.print(" , Tiempo respuesta : "); Serial.print(avg_time_ms); Serial.print(" ms"); publishSwitchState_IP(ipToString(ip_ping), true); } else { respuesta_ping[nIP] = 0; ultima_llamada_ping[nIP] = 0; Serial.print(" , Error : No contesta"); publishSwitchState_IP(ipToString(ip_ping), false); } Serial.println(""); ultima_llamada_ping[nIP] = millis(); } else{ Serial.print(" *** Ip omitida *** por delay_off"); segundos = (( ultima_llamada_ping[nIP] + delay_off ) - millis() ); Serial.print(" , siguiente ciclo en : "); Serial.print(segundos/1000); Serial.println(" Segs."); } digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED)); } digitalWrite(BUILTIN_LED, false ); } void ping_only_connected() { IPAddress ip_ping = WiFi.localIP(); const byte peticiones_ping = 3; Serial.println("----> Ip comprobar solo con conexion : "); for (nIP = 1; nIP <= 255; nIP++) { if (respuesta_ping[nIP] > 0) { ip_ping[3] = nIP; Serial.print(" - "); Serial.print(ip_ping); if ((tiempo_entre_llamadas(ultima_llamada_ping[nIP]) == true) || ( respuesta_ping[nIP] == 0)){ if (Ping.ping(ip_ping, peticiones_ping)) { // Serial.println("Contesta ... "); int avg_time_ms = Ping.averageTime(); respuesta_ping[nIP] = avg_time_ms; Serial.print(" , Tiempo respuesta : "); Serial.print(avg_time_ms); Serial.print(" ms"); publishSwitchState_IP(ipToString(ip_ping), true); } else { respuesta_ping[nIP] = 0; ultima_llamada_ping[nIP] = 0; Serial.print(" , Error : No contesta"); publishSwitchState_IP(ipToString(ip_ping), false); } Serial.println(""); ultima_llamada_ping[nIP] = millis(); } else{ Serial.print(" *** Ip omitida *** por delay_off"); segundos = (( ultima_llamada_ping[nIP] + delay_off ) - millis() ); Serial.print(" , siguiente ciclo en : "); Serial.print(segundos/1000); Serial.println(" Segs."); } digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED)); } } digitalWrite(BUILTIN_LED, false ); } void ping_only_selected() { const byte peticiones_ping = 5; IPAddress ip_ping ; boolean activo; Serial.println("----> Comprobar solo IPs prioritarias : "); for (int i = 0; i < sizeof(ip_prioritarias) / 4; i++) { ip_ping[0] = ip_prioritarias[i][0]; ip_ping[1] = ip_prioritarias[i][1]; ip_ping[2] = ip_prioritarias[i][2]; ip_ping[3] = ip_prioritarias[i][3]; Serial.print(" - "); Serial.print(ip_ping); activo = false; if (Ping.ping(ip_ping, peticiones_ping)) { // Serial.println("Contesta ... "); int avg_time_ms = Ping.averageTime(); activo = true; respuesta_ping[ip_prioritarias[i][3]] = avg_time_ms; Serial.print(" : Tiempo respuesta : "); Serial.print(avg_time_ms); Serial.print(" ms"); publishSwitchState_IP(ipToString(ip_ping), true); } if (tiempo_entre_llamadas(ultima_llamada_ping[ip_ping[3]]) == true){ if (activo == true){ ultima_llamada_ping[ip_ping[3]] = millis(); //Reiniciamos el contador de tiempo } else { respuesta_ping[ip_prioritarias[i][3]] = 0; Serial.print(" : Error : No contesta"); publishSwitchState_IP(ipToString(ip_ping), false); } } Serial.println(""); digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED)); } digitalWrite(BUILTIN_LED, false ); delay(250); } void loop() { long ahora = millis(); long lastReconnectAttempt; time_t t = now(); //WIFI if (WiFi.status() != WL_CONNECTED) //comprobar estado de conexion del WIFI { WiFi.begin(ssid_wifi_seleccionado, password_wifi_seleccionado); delay(1000); } //MQTT if (!mqttClient.connected()) { long now = millis(); if (now - lastReconnectAttempt > 5000) { if (reconnect()) { lastReconnectAttempt = 0; } } } else { mqttClient.loop(); } ArduinoOTA.handle(); //Modo escaneo toda la red if ( ip_mode == IP_MODE_ALL ) { switch (nCiclo) { case 0: ping_only_selected(); break; case 1: ping_all_netwotk(); break; case 2: ping_only_connected(); break; case 3: ping_only_connected(); break; case 4: ping_only_selected(); nCiclo = 0; break; default: nCiclo = 0; break; } } //Modo escaneo solo de los activos if ( ip_mode == IP_MODE_ONLY_ACTIVE ) { if ( nCiclo == 0 ) { ping_all_netwotk(); } else { ping_only_connected(); } if ( nCiclo > 25 ) { nCiclo = 0; } } //Modo escaneo solo de los conocidos if ( ip_mode == IP_MODE_ONLY_KNOWN ) { ping_only_selected(); // if ( nCiclo < 100 ) { // ping_only_selected(); // } // else { // ping_all_netwotk(); // } if ( nCiclo > 100 ) { nCiclo = 0; } // delay(250); } //Modo escaneo alternado 1/32 parte de la red cada vez if ( ip_mode == IP_MODE_ALTERNATE ) { for (int i = 0; i < 32; i++){ ping_only_selected(); ping_only_selected(); ping_only_selected(); ping_only_selected(); ping_only_selected(); ping_alternate(i*8,(i*8)+7); } } nCiclo++; } String ipToString(IPAddress ip) { String s = ""; for (int i = 0; i < 4; i++) s += i ? "." + String(ip[i]) : String(ip[i]); return s; }