ESP8266 With Websockets

About: Fundador de The Inventor's House Hackerspace, Movimiento Maker y Hardware Libre, DIY, Workaholic

Intro: ESP8266 With Websockets

Hola amigos

Hoy les voy enseñar como usar websockets con el modulo WiFi ESP8266 conectándose a un servidor con nodejs implementado en un contador de personas, este ejemplo lo realizamos para el concurso de Flextronics en Campus Party 5 con la intención de saber cuantas personas están dentro de un lugar.

Demo Web: www.dbug.mx:8000

Comencemos

Step 1: Material

Lo que vamos a necesitar para realizar este proyecto es:

  • ESP8266
  • LM358
  • 6 Leds infrarrojos
  • 2 fototransistores
  • 6 resistencias de 10k
  • 2 resistencias de 4.7k
  • 2N2222

Este es el material utilizado en nuestro contador de personas

Step 2: Server Nodejs

Lo primero que debemos hacer es clonar el repositorio

https://github.com/theinventorshouse/iot-counter

git clone  https://github.com/theinventorshouse/iot-counter....
cd iot-counter

Una vez clonado el repositorio para arrancar nuestro servidor debemos tener instalado nodejs y podremos levantar el servidor con los siguientes comandos

cd server-socket
npm install npm start

La configuracion por defecto es

Hardware Socket: PORT 3000
Website: PORT 8000

Step 3: ESP8266 Websockets

Para cargar el firmware debes de abrir el proyecto hardware-counter que se encuentre en la carpeta del mismo nombre en tu Arduino IDE (con el plugin de ESP instalado puedes ver como instalarlo en el siguiente instructable paso 2)

Importante: Recuerda incluir los datos necesarios para hacer las pruebes en tu red (SSID, Password, IPServer)

/* * Autores: * Andres Sabas  * Iddar Olivares  * Creado: Julio 2015 * Contador de personas con * ESP8266 Version 12 */
#include #include #include #include #define SSID "Wifi Name"#define PASSWORD "Wifi password"#define SERVER_PORT 3000#define SERVER_IP "104.236.241.103"#define USE_SERIAL Serial WebSocketsClient webSocket;int StatusFlag = 0; void webSocketEvent(WStype_t type, uint8_t * payload, size_t lenght) { switch(type) { case WStype_DISCONNECTED: USE_SERIAL.printf("[WSc] Disconnected!\n"); break; case WStype_CONNECTED: USE_SERIAL.print("[WSc] Connected to url:dbug.mx "); break; } } void setup() { pinMode(4,INPUT); pinMode(13,INPUT); pinMode(5,OUTPUT); attachInterrupt(13, inPeople, RISING); attachInterrupt(4, outPeople, RISING); digitalWrite(5,HIGH); //Informacion de Depuración USE_SERIAL.begin(115200); USE_SERIAL.setDebugOutput(true); USE_SERIAL.println(); USE_SERIAL.println(); for(uint8_t t = 4; t > 0; t--) { USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); USE_SERIAL.flush(); delay(1000); } WiFi.begin(SSID, PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(100); } //Conexion al servidor webSocket.begin(SERVER_IP, SERVER_PORT); webSocket.onEvent(webSocketEvent);} void loop() { webSocket.loop(); //Activacion de interrupciones attachInterrupt(13, inPeople, RISING); attachInterrupt(4, outPeople, RISING); // Envio de datos a servidor if(StatusFlag == 1) { webSocket.sendTXT("in", 2); StatusFlag = 0; USE_SERIAL.println("in"); } if(StatusFlag == 2) { webSocket.sendTXT("out", 3); StatusFlag = 0; USE_SERIAL.println("out"); } delay(1500);} void inPeople() { while(digitalRead(13)) { detachInterrupt(4); } StatusFlag = 1;} void outPeople() { while(digitalRead(4)) { detachInterrupt(13); } StatusFlag = 2;}

Step 4: Circuito

El circuito es como el que se muestra en las imágenes, donde tenemos algunos leds que emiten una luz infrarroja que choca contra los fototransistores y al momento de que una persona cruza la puerta se corta el haz de luz y se activa la interrupción en el esp8266 que envía al servidor un si alguien a entrado o salido.

Step 5: Funcionando

Una vez terminado el circuito, colocados los leds y fototransistores podremos hacer la conexión con el servidor local u online como en que nosotros tenemos funcionando.

Demo Web: www.dbug.mx:8000

El servidor puede mostar cuentas personas hay en el lugar, hace cuanto tiempo salio o entro una personas y la cantidad de personas que han salido o entrado en el transcurso del día.

Espero esto les sirva para próximos proyectos, saludos inventores

Share

    Recommendations

    • Audio Contest 2018

      Audio Contest 2018
    • Optics Contest

      Optics Contest
    • Electronics Tips & Tricks Challenge

      Electronics Tips & Tricks Challenge

    4 Discussions

    0
    None
    MayckB

    Question 7 weeks ago on Step 1

    I need help with the code please;

    _------------------------------------------------------------------------_---------------------------------------------
    arduino ide y nodemcu esp8266


    #include <esp8266wifi.h>
    #include <wificlient.h>
    #include <esp8266webserver.h>
    #include <websocketsserver.h>
    #include <hash.h>
    #include <fs.h>

    const char *ssid = "name_wifi";
    const char *password = "passpass";

    bool StatusComedor;

    const char COMEDOR_ON[]= "1";
    const char COMEDOR_OFF[]="0";

    int16_t thisRead = 0;
    int16_t lastRead = 0;
    uint8_t counter = 0;

    WebSocketsServer webSocket = WebSocketsServer(81);
    ESP8266WebServer server(80);

    void setup(void){
    delay(1000);

    Serial.begin(115200);

    pinMode(16, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(0, OUTPUT);
    pinMode(2, OUTPUT);
    pinMode(12, OUTPUT);
    pinMode(15, OUTPUT);
    pinMode(3, OUTPUT);

    WiFi.begin(ssid, password);
    Serial.println("Iniciando conexión a modem infinitum");
    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }
    IPAddress myIP = WiFi.localIP();
    Serial.println("");
    Serial.print("Direccion IP: ");
    Serial.println(myIP);

    SPIFFS.begin();

    webSocket.begin();
    webSocket.onEvent(webSocketEvent);

    server.onNotFound([](){
    if(!handleFileRead(server.uri()))
    server.send(404, "text/plain", "FileNotFound");
    });
    server.begin();
    Serial.println("Servidor web iniciado");
    }
    void loop() {
    webSocket.loop();
    server.handleClient();

    counter++;
    if(counter == 255) {
    counter=0;
    thisRead = map(analogRead(A0), 900, 20, 0, 100);

    if (thisRead > 100) thisRead = 100;
    if(thisRead < 0) thisRead = 0;

    if (thisRead != lastRead){
    String message = String(thisRead);
    webSocket.broadcastTXT(message);
    }
    lastRead = thisRead;
    }
    }
    //FUNCION PROPIA DEL OBJETO WEBSOCKET
    void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght) {
    Serial.printf("webSocketEvent(%d, %d, ...)\r\n", num, type);
    switch(type) {
    // CASO CUANDO SE DESCONECTA UN USUARIO DEL WEBSOCKET
    case WStype_DISCONNECTED: {
    Serial.printf("Usuario #%u - Desconectado!\n", num);
    break;
    }
    case WStype_CONNECTED: {
    IPAddress ip = webSocket.remoteIP(num);
    Serial.printf("Conexión establecida desde la IP: %d.%d.%d.%d Nombre: %s url: %u\n", ip[0], ip[1], ip[2], ip[3], payload, num);
    if(StatusComedor==true){
    webSocket.sendTXT(num, COMEDOR_ON, strlen(COMEDOR_ON));
    }else if(StatusComedor==false){
    webSocket.sendTXT(num, COMEDOR_OFF, strlen(COMEDOR_OFF));
    }

    String message = String(lastRead);
    webSocket.broadcastTXT(message);
    break;
    }
    case WStype_TEXT: {
    String incoming = "";
    for (int i = 0; i < lenght; i++) {
    incoming.concat((char)payload[i]);
    }
    Serial.print(incoming);
    Serial.println("");
    uint8_t valor = incoming.toInt();
    if(valor==1){
    digitalWrite(16, HIGH);
    StatusComedor=true;
    }else if(valor==0){
    digitalWrite(16, LOW);
    StatusComedor=false;
    }

    uint8_t valor2 = incoming.toInt();
    if(valor2==3){
    digitalWrite(5, HIGH);
    }else if(valor2==2){
    digitalWrite(5, LOW);
    }

    uint8_t valor3 = incoming.toInt();
    if(valor3==5){
    digitalWrite(4, HIGH);
    }else if(valor3==4){
    digitalWrite(4, LOW);
    }

    uint8_t valor4 = incoming.toInt();
    if(valor4==7){
    digitalWrite(0, HIGH);
    }else if(valor4==6){
    digitalWrite(0, LOW);
    }

    uint8_t valor5 = incoming.toInt();
    if(valor5==9){
    digitalWrite(2, HIGH);
    }else if(valor5==8){
    digitalWrite(2, LOW);
    }

    uint8_t valor6 = incoming.toInt();
    if(valor6==11){
    digitalWrite(14, HIGH);
    }else if(valor6==10){
    digitalWrite(14, LOW);
    }

    uint8_t valor7 = incoming.toInt();
    if(valor7==13){
    digitalWrite(12, HIGH);
    }else if(valor7==12){
    digitalWrite(12, LOW);
    }

    uint8_t valor8 = incoming.toInt();
    if(valor8==15){
    digitalWrite(15, HIGH);
    }else if(valor8==14){
    digitalWrite(15, LOW);
    }

    uint8_t valor9 = incoming.toInt();
    if(valor9==17){
    digitalWrite(3, HIGH);
    }else if(valor9==16){
    digitalWrite(3, LOW);
    }
    break;
    }
    }
    }

    // A function we use to get the content type for our HTTP responses
    String getContentType(String filename){
    if(server.hasArg("download")) return "application/octet-stream";
    else if(filename.endsWith(".htm")) return "text/html";
    else if(filename.endsWith(".html")) return "text/html";
    else if(filename.endsWith(".css")) return "text/css";
    else if(filename.endsWith(".js")) return "application/javascript";
    else if(filename.endsWith(".png")) return "image/png";
    else if(filename.endsWith(".gif")) return "image/gif";
    else if(filename.endsWith(".jpg")) return "image/jpeg";
    else if(filename.endsWith(".ico")) return "image/x-icon";
    else if(filename.endsWith(".xml")) return "text/xml";
    else if(filename.endsWith(".pdf")) return "application/x-pdf";
    else if(filename.endsWith(".zip")) return "application/x-zip";
    else if(filename.endsWith(".gz")) return "application/x-gzip";
    return "text/plain";
    }
    // Takes a URL (for example /index.html) and looks up the file in our file system,
    // Then sends it off via the HTTP server!
    bool handleFileRead(String path){
    #ifdef DEBUG
    Serial.println("handleFileRead: " + path);
    #endif
    if(path.endsWith("/")) path += "index.html";
    if(SPIFFS.exists(path)){
    File file = SPIFFS.open(path, "r");
    size_t sent = server.streamFile(file, getContentType(path));
    file.close();
    return true;
    }
    return false;
    }

    html..-----------------------------------------------------------------------------------------------------------....

    <html lang="es">
    <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="css/index.css">
    <meta name="viewport" content="width=device-width, user-scalable=no">
    <title>ByR Hogar</title>
    </head>
    <body>
    <div>
    <h1>ByR Control Hogar</h1>
    <hr>
    <div>
    RADIO
    TV
    Camara
    </div>
    <h3>CONTROL DE LUCES</h3>
    <div>
    <div>
    <div>
    <input type="checkbox" onclick="enviarComedor()" id="comedor">
    <label for="comedor" id="StatusComedor">COMEDOR</label>
    </div>
    <div>
    <input type="checkbox" onclick="enviarAlacena()" id="alacena">
    <label for="alacena" id="StatusAlacena">ALACENA</label>
    </div>
    </div>
    <div>
    <input type="checkbox" onclick="enviarDormitorio()" id="dormitorio">
    <label for="dormitorio" id="StatusDormitorio">DORMITORIO</label>

    <input type="checkbox" onclick="enviarLampara()" id="lampara">
    <label for="lampara" id="StatusLampara">LAMPARA</label>
    </div>
    <div>
    <input type="checkbox" onclick="enviarBaño()" id="baño">
    <label for="baño" id="StatusBaño">BAÑO</label>

    <input type="checkbox" onclick="enviarTocador()" id="tocador">
    <label for="tocador" id="StatusTocador">TOCADOR</label>
    </div>
    <div>
    <h3>CONTROL DE ACCESORIOS</h3>
    <div>
    <input type="checkbox" onclick="enviarCalefactor()" id="calefactor">
    <label for="calefactor" id="StatusCalefactor">CALEFACTOR</label>
    </div>
    <div>
    <input type="checkbox" onclick="enviarPuerta()" id="puerta">
    <label for="puerta" id="StatusPuerta">PUERTA</label>
    </div>
    <div>
    <input type="checkbox" onclick="enviarVentilador()" id="ventilador">
    <label for="ventilador" id="StatusVentilador">VENTILADOR</label>
    </div>
    </div>
    <div>
    <div>
    <h3>TEMPERATURA</h3>
    <label>24°C</label>
    </div>
    <div>
    <h3>HUMEDAD</h3>
    <label>28 %</label>
    </div>
    </div>
    </div>
    <hr>
    <h4>TECNOLOGIA Y HOGAR</h4>

    Gracias a la tecnología cada uno de nuestros artefactos eléctricos y electrónicos, en la actualidad los podemos controlar de manera inalámbrica, ya sea por "Control remoto, Bluetooth, Wifi", y hoy lo podemos hacer via internet; Gracias al "Internet de las cosas(IOT)", y una tecnología muy indispensable, como lo es "WebSocket".


    <footer>Diseñado por Michel Bernales © 2018 ¡Todos los derechos son para uso personal.!</footer>
    </div>
    <script type="text/javascript" src="javascript/reloj.js"></script>
    <script type="text/javascript" src="javascript/index.js"></script>
    </body>
    </html>

    javascript....----------------------------------------------------------------------------------------------------....

    var Socket = new WebSocket('ws://' + window.location.hostname + ':81');
    Socket.onopen = function(evt) {
    console.log('Conexión abierta' + new Date());
    };
    Socket.onclose = function(evt) {
    console.log('Conexión cerrada');
    };
    Socket.onerror = function(evt) {
    console.log(evt.data);
    };
    Socket.onmessage = function(evt){
    console.log(evt);

    var c=document.getElementById('StatusComedor');
    if (StatusComedor==true) {
    c.style.background='#2DB30B';
    }else if(StatusComedor==false){
    c.style.background='red';
    }
    };

    function enviarComedor(c){
    Socket.send(c.id);
    }
    function enviarComedor() {
    var e=document.getElementById('comedor');
    if(e.checked==true){
    Socket.send('1');
    }else if(e.checked==false){
    Socket.send('0');
    }
    }
    function enviarAlacena(){
    var e=document.getElementById('alacena');
    if(e.checked==true){
    Socket.send('3');
    }else if(e.checked==false){
    Socket.send('2');
    }
    }
    function enviarDormitorio(){
    e=document.getElementById('dormitorio');
    if(e.checked==true){
    Socket.send('5');
    }else if(e.checked==false){
    Socket.send('4');
    }
    }
    function enviarLampara(){
    e=document.getElementById('lampara');
    if(e.checked==true){
    Socket.send('7');
    }else if(e.checked==false){
    Socket.send('6');
    }
    }
    function enviarBaño(){
    e=document.getElementById('baño');
    if(e.checked==true){
    Socket.send('9');
    }else if(e.checked==false){
    Socket.send('8');
    }
    }
    function enviarTocador(){
    e=document.getElementById('tocador');
    if(e.checked==true){
    Socket.send('11');
    }else if(e.checked==false){
    Socket.send('10');
    }
    }
    function enviarCalefactor(){
    e=document.getElementById('calefactor');
    if(e.checked==true){
    Socket.send('13');
    }else if(e.checked==false){
    Socket.send('12');
    }
    }
    function enviarPuerta(){
    e=document.getElementById('puerta');
    if(e.checked==true){
    Socket.send('15');
    }else if(e.checked==false){
    Socket.send('14');
    }
    }
    function enviarVentilador(){
    e=document.getElementById('ventilador');
    if(e.checked===true){
    Socket.send('17');
    }else if(e.checked==false){
    Socket.send('16');
    }
    }

    As you will see the code, I tell you that it works but when you load the page, it returns to the state of off the button and red color

    the other clients do not see the state that another executes, I need help I am a novice, thank you very much friend in what you can help me.
    Captura de pantalla (41).png
    0
    None
    maomarest

    3 years ago on Introduction

    Me queda una duda, uno puede acceder desde cualquier sitio o solo desde la red WLAN, es decir, en dado caso podria ver la cantidad de personas desde cualquier parte del mundo?

    1 reply
    0
    None
    LucasV16maomarest

    Reply 3 years ago

    Hola mestrada3, lo que tenes que hacer para ver tu sitio desde WAN es hacer forwarding de tu puerto local en tu router, a un puerto que puedas ver desde afuera. Ejemplo: Si tu servidor corre en: 192.168.1.3:8080 , le "decís" al router que si recibe una petición a [TU_IP_PUBLICA]:[PUERTO_Ext] lo mapeé hacia el socket 192.168.1.3:8080. Así de simple. Si buscás tutoriales de como abrír puertos en tu router, seguro encontrás uno. Saludos!