OBJETIVOS
Esta práctica es una continuación de la Práctica 3 . El principal objetivo es establecer una conexión remota entre la placa NodeMCU y un dispositivo conectado a internet (PC, smartphone, tablet, etc.) para controlar el encendido/apagado de un LED.
Debemos entender este procedimiento como genérico, ya que una vez entendido podemos utilizarlo con otros objetivos de accesos remotos como pudiera ser realizar medición de temperaturas, medición luminosidad, control de un luces, control de motores, etc., en definitiva, obtener cualquier dato o realizar cualquier acción sobre los dispositivos o sensores que podamos conectar a la placa desde cualquier sitio del mundo.
MATERIAL NECESARIO
CONCEPTOS BÁSICOS
A continuación podemos ver el esquema básico una conexión remota entre un smartphone y una placa NodeMCU.
El smartphone está conectado a Internet y el NodeMCU al punto de acceso de la red local (router). La comunicación entre ambos dispositivos se realiza a petición del smartphone introduciendo la dirección IP pública del router + el puerto de comunicación entre el router y el NodeMCU en su red local. La unión de estos dos parámetros se denomina socket. En el ejemplo el socket sería: 188.78.24.213:80
Veamos como conocer las direcciones IP necesarias para realizar la conexión y como realizar la configuración de los equipos.
DIRECCIONES IP: IPs privadas e IPs públicas
Las Direcciones de Internet Protocol (IP) son las etiquetas numéricas usadas para identificar, de manera única, un cliente de una red (Host), localizarlo en la red y, de ese modo encaminar paquetes IP entre clientes. Con este objetivo, las direcciones IP aparecen en campos de la cabecera, indicando el origen y destino del paquete.
El protocolo que se utiliza actualmente es el IPv4, aunque actualmente se está impulsando el protocolo IPv6, que está en las primeras fases de implantación.
- En el protocolo IPv4 las direccione IP se pueden escribir de forma que expresen un entero de 32 bits, aunque normalmente se representan con decimales separados por puntos. El número de direcciones que admite este protocolo es de 232 = 4 294 967 296 direcciones.
- En el protocolo IPv6, las direcciones tienen 128 bits. Se representa mediante ocho grupos de cuatro dígitos hexadecimales, cada grupo representando 16 bits (dos octetos). Los grupos se separan mediante dos puntos (:). El número de direcciones que admite este protocolo es de 232 = 340.282.366.920.938.463.463.374.607.431.768.211.456 direcciones.
Debemos recordar que aunque las personas habitualmente utilizamos dos dominios para conectarnos a un servidor, los servidores de nombres de dominio (Domain Name Servers – DNS), realizan de manera automática la conversión entre el nombre de dominio y la IP para que se pueda realizar la conexión.
Por ejemplo, para conectarnos a Google podemos escribir tanto http://www.google.es como 74.125.196.105
IP privada e IP pública
- La IP privada es la dirección que identifica a cada uno de los dispositivos conectados en nuestra red local (Local Area Network – LAN). Las IPs privadas son únicamente visibles para los dispositivos conectados en la red.
En la anterior práctica vimos que con la instrucción WiFi.localIP() podemos ver la IP privada que asigna el punto de acceso a la placa cuando se realiza la conexión.
- La IP pública es la dirección que identifica nuestra red desde el exterior. Es única y nos la da nuestro proveedor de Internet.
Tanto la IP privada, como la IP pública, generalmente son dinámicas, es decir, van cambiando, aunque se dan las siguientes circunstancias:
- Las IPs privadas las asigna el router a cada uno de los clientes de la red local tienen persistencia, es decir, que el router va almacenando el nombre de cliente (hostname), su MAC (macAddress) y la dirección IP local asignada (localIP), para mantenerla en futuras conexiones.
En cualquier caso, siempre podemos forzar una IP local fija con la instrucción WiFi.config() vista en la anterior práctica.
- Las IPs públicas son dinámicas, salvo que el proveedor de Internet nos preste el servicio de IP fija, con un coste aproximado de 10 €/mes o hayamos instalado algún programa o contratado algún servicio para mantenerlas como los que se prestan en http://www.no-ip.com.
En cualquier caso, el cambio de IP, siendo dinámica, se produce cada varios días (si no reseteamos el router), por lo que no tendremos problemas para ejecutar esta práctica.
MAPEADO DE PUERTOS
El mapeado (conocido como portforward), consiste en dirigir el tráfico de comunicaciones que llega al punto de acceso (router) desde fuera de la red, a través de un puerto de comunicaciones, hacia la IP local con la que se quiere conectar. En el ejemplo de la imagen se dirige el tráfico desde la IP pública 188.78.24.213 a la IP local 192.168.1.125 a través del puerto nº 80.
Cuando mapeamos, lo que hacemos es interrelacionar los puertos del punto de acceso con las direcciones IPs locales.
Existen 65536 puertos en un router (216 – desde el 0 hasta el 65535). La IANA (Internet Assigned Numbers Authority) estableció un estándar de asignación que se los divide en tres categorías:
- Del 0 al 1023 -puertos conocidos-. Reservados para el sistema operativo y los protocolos más utilizados como, por ejemplo, el 21 para FTP, el 25 para el SMTP o el 80 para HTTP.
- Del 1024 al 49151 -puertos registrados-. Para la mayoría de aplicaciones y por norma general para configurar nuestras conexiones.
- Del 49152 al 65535 -puertos dinámicos y/o privados-. Reservados a las aplicaciones que necesitan conectarse a un servidor.
Cada router de cada fabricante tiene un procedimiento específico para realizar el mapeado de puertos, por lo que habrá que buscar la documentación específica para ver como hay que hacerlo en cada caso.
A continuación se explica el mapeado del modelo F680 de fabricante ZTE a modo de ejemplo.
- En primer lugar hay que acceder al router a través de un navegador Web de un cliente conectado en red local. La dirección de acceso es 192.168.1.1. En la pantalla inicial deberemos introducir el nombre de usuario y contraseña que nos haya proporcionado el proveedor del servicio de Internet.
- Después de haber accedido al router, seleccionaremos Application → Application List → Click here to add an application.
- Elegimos un nombre para reconocer el mapeado que estamos realizando. A continuación elegimos el protocolo de comunicaciones TCP (Transmission Control Protocol – TCP), ya que este protocolo garantiza que los datos serán entregados en su destino sin errores y en el mismo orden en que se transmitieron. Por último elegimos el rango de puertos a abrir.
Dado que en el sketch usaremos como puerto de comunicaciones el nº 80, en el mapeado abriremos únicamente ese puerto (será el número de puerto de inicio y fin).
- Únicamente queda vincular la IP en la que está conectado el módulo (192.168.1.133) con el puerto que hemos abierto -el nº 80– a través del nombre que hemos elegido para el mapeado.
Una vez repasado esto, estaremos listos para construir el circuito y subir el sketch a la placa NodeMCU.
CIRCUITO ELECTRÓNICO
SKETCH
El sketch a subir al NodeMCU será el siguiente:
/* NodeMCU Server - Conexión en modo Station con un punto de acceso (router) por Dani No www.esploradores.com Crea una conexión del NodeMCU en modo Station con un punto de acceso que permite encender y apagar un LED conectado a la salida D4 (GPIO02) del módulo NodeMCU. Este código de ejemplo es de público dominio. */ #include <ESP8266WiFi.h> //Incluye la librería ESP8266WiFi const char* ssid = "xxxxxxxxxxx"; //Indicamos el nombre de la red WiFi (SSID) a la que queremos conectarnos. const char* password = "xxxxxxxxxxx"; //Indicamos la contraseña de de red WiFi WiFiServer server(80); //Definimos el puerto de comunicaciones int PinLED = 2; // GPIO2 //Definimos el pin de salida - GPIO2 / D4 int estado = LOW; //Definimos la variable que va a recoger el estado del LED void setup() { Serial.begin(115200); Serial.println(); pinMode(PinLED, OUTPUT); //Inicializamos el GPIO2 como salida digitalWrite(PinLED, LOW); //Dejamos inicialmente el GPIO2 apagado WiFi.begin(ssid, password); //Inicializamos la conexión del chip ESP8266 con la red WiFi Serial.printf("Conectando a la red: %s\n", WiFi.SSID().c_str()); while (WiFi.status() != WL_CONNECTED) { // Verifica el estado de la conexión del NodeMCU cada 0,5s hasta que conecta delay(500); Serial.print("."); } WiFi.setAutoReconnect(true); // Realiza la reconexión a la red WiFi si se pierde la conexión Serial.println(""); Serial.println("WiFi conectada"); // Indica que el NodeMCU conectado con la red WiFi server.begin(); // Inicia el NodeMCU en modo Station Serial.println("Servidor inicializado"); Serial.printf("Utiliza esta URL para conectar: http://%s\n", WiFi.localIP().toString().c_str()); } void loop(){ WiFiClient client = server.available(); // Comprueba si el cliente ha conectado if (!client) { return; } Serial.println("nuevo cliente"); // Espera hasta que el cliente envía alguna petición while(!client.available()){ delay(1); } String peticion = client.readStringUntil('\r'); // Lee la petición Serial.println(peticion); client.flush(); // Comprueba la petición if (peticion.indexOf('/LED=ON') != -1) { estado = HIGH; } if (peticion.indexOf('/LED=OFF') != -1){ estado = LOW; } digitalWrite(PinLED, estado); //Enciende o apaga el LED en función de la petición client.println("HTTP/1.1 200 OK"); //Envía la página HTML de respuesta al cliente client.println(""); //No olvidar esta línea de separación client.print("<h1 align=center>EL LED ESTA AHORA: "); if(estado == HIGH) { client.print("ENCENDIDO</h1>"); client.print("<img src='https://esploradores.com/Practicas_html/LED_encendido.png' alt='Bombilla encendida' style='display:block; margin:auto' width='15%'>"); client.print("<input type='image' src='https://esploradores.com/Practicas_html/apagar_300x88.png' style='display:block; margin:auto' width='25%' onClick=location.href='/LED=OFF'>"); } else { client.print("APAGADO</h1>"); client.print("<img src='https://esploradores.com/Practicas_html/LED_apagado.png' alt='Bombilla apagada' style='display:block; margin:auto' width='15%'>"); client.print("<input type='image' src='https://esploradores.com/Practicas_html/encender_300x88.png' style='display:block; margin:auto' width='25%' onClick=location.href='/LED=ON'>"); } client.println("</html>"); delay(1); Serial.println("Peticion finalizada"); // Se finaliza la petición al cliente. Se inicializa la espera de una nueva petición. Serial.println(""); }
CONEXIÓN CON EL ACCESS POINT
Para poder conectar con el NodeMCU, únicamente tendremos que escribir el socket (http://188.78.24.213:80 en el ejemplo), desde un navegador Web conectado a Internet. Inmediatamente visualizaremos la página Web que nos servirá para controlar el encendido o apagado del LED.
54 Comments
Leave your reply.