¿Cómo construir un servidor web con el ESP32 que muestre una página web con múltiples sliders?

Libro Guía del Microcontrolador ESP32

Este tutorial te muestra cómo construir un servidor web con el ESP32 que muestra una página web con múltiples sliders. Los sliders controlan el ciclo de trabajo (duty cycle) de diferentes canales PWM para controlar la intensidad de varios LEDs.

En lugar de LEDs, puedes usar este proyecto para controlar motores DC u otros actuadores que requieran una señal PWM. La comunicación entre los clientes y el ESP32 se realiza usando el protocolo WebSocket. Además, cada vez que hay un cambio, todos los clientes actualizan sus valores de slider simultáneamente.

También puedes modificar el código presentado en este tutorial para añadir sliders a tus proyectos y establecer valores umbral o cualquier otro valor que necesites usar en tu código.

Para este proyecto, la placa ESP32 se programará usando el core de Arduino. Puedes usar Arduino IDE, VS Code con PlatformIO o cualquier otro IDE adecuado.

Para comprender mejor cómo funciona este proyecto, te recomendamos echar un vistazo a los siguientes tutoriales: PWM en el ESP32 con Arduino IDE (Salida Analógica), Servidor WebSocket en el ESP32: Controla Salidas (Arduino IDE) y Servidor Web en el ESP32 con Slider: Controla la Intensidad de un LED (PWM).

Nota: el último tutorial muestra cómo construir un servidor web con un solo slider, pero usa peticiones HTTP. En este tutorial usaremos el protocolo WebSocket, que permite actualizaciones en tiempo real para todos los clientes.

Resumen del proyecto

La página web que construiremos contiene tres tarjetas. Cada tarjeta tiene un párrafo para mostrar el título de la tarjeta (Fader 1, Fader 2, Fader 3). Hay un slider de tipo range en cada tarjeta que puedes mover para establecer la intensidad del LED correspondiente. En cada tarjeta, otro párrafo muestra la intensidad actual del LED (en porcentaje). Cuando estableces una nueva posición para el slider, se actualizan todos los clientes (si tienes varias pestañas de navegador abiertas o varios dispositivos, se actualizan casi simultáneamente cada vez que hay un cambio).

Cómo funciona

El ESP32 aloja un servidor web que muestra una página web con tres sliders. Cuando estableces una nueva posición para un slider, el cliente envía el número de slider y el valor del slider al servidor vía protocolo WebSocket. Por ejemplo, si estableces el slider número 3 en la posición 40, enviaría el mensaje 3s40 al servidor.

El servidor (ESP32) recibe el número de slider y el valor correspondiente y ajusta el ciclo de trabajo del PWM en consecuencia. Además, también notifica a todos los otros clientes con los nuevos valores actuales de los sliders, lo que nos permite tener todos los clientes actualizados casi instantáneamente.

El ESP32 emite la señal PWM con el ciclo de trabajo correspondiente para controlar la intensidad del LED. Un ciclo de trabajo del 0% significa que el LED está completamente apagado, un ciclo de trabajo del 50% significa que el LED está medio encendido, y un ciclo de trabajo del 100% significa que el LED está completamente encendido.

Cada vez que abres una nueva ventana de navegador (esto es cuando un nuevo cliente se conecta), enviará un mensaje al ESP32 (también a través del protocolo WebSocket) con el mensaje getValues. Cuando el ESP32 recibe este mensaje, envía los valores actuales de los sliders. De esta forma, cada vez que abres una nueva pestaña, siempre muestra los valores actuales y actualizados.

Requisitos previos

Antes de proceder con este tutorial, asegúrate de revisar todos los siguientes requisitos previos.

1) Componentes necesarios

Para seguir este proyecto necesitas: una placa ESP32, 3 LEDs, 3 resistencias de 220 Ω, una protoboard y cables jumper.

No necesitas tres LEDs para probar este proyecto; puedes simplemente ver los resultados en el Monitor Serie o usar otros actuadores que requieran una señal PWM para funcionar.

2) Arduino IDE y complemento de placas ESP32

Vamos a programar el ESP32 usando Arduino IDE. Así que debes tener el complemento ESP32 instalado. Si quieres usar VS Code con la extensión PlatformIO, sigue el tutorial correspondiente para aprender a programar el ESP32.

3) Plugin de carga de sistema de archivos

Para subir los archivos HTML, CSS y JavaScript necesarios para construir este proyecto a la memoria flash del ESP32 (LittleFS), usaremos un plugin para Arduino IDE: LittleFS Filesystem Uploader. Sigue el tutorial correspondiente para instalar el plugin de carga de sistema de archivos si aún no lo tienes instalado.

Si estás usando VS Code con la extensión PlatformIO, lee el tutorial correspondiente para aprender a subir archivos al sistema de archivos LittleFS.

4) Librerías

Para construir este proyecto, necesitas instalar las siguientes librerías: la libería Arduino_JSON de Arduino versión 0.1.0, la libería ESPAsyncWebServer de ESP32Async y la libería AsyncTCP de ESP32Async.

Puedes instalar las librerías usando el Gestor de Librerías de Arduino. Ve a Programa > Incluir Librería > Gestionar Librerías y busca los nombres de las librerías.

Esquema de conexión

Conecta tres LEDs al ESP32. Estamos usando GPIOs 12, 13 y 14. Puedes usar cualquier otro GPIO adecuado. Cada LED debe ir con su resistencia de 220 Ω en serie hacia GND, con el ánodo conectado al GPIO correspondiente.

Organizar tus archivos

Para mantener el proyecto organizado y hacerlo más fácil de entender, crearemos cuatro archivos para construir el servidor web: el sketch de Arduino que maneja el servidor web, index.html para definir el contenido de la página web, style.css para estilizar la página web, y script.js para programar el comportamiento de la página web (manejar qué ocurre cuando mueves el slider, enviar, recibir e interpretar los mensajes recibidos vía protocolo WebSocket).

Debes guardar los archivos HTML, CSS y JavaScript dentro de una carpeta llamada data dentro de la carpeta del sketch de Arduino. Subiremos estos archivos al sistema de archivos del ESP32 (LittleFS).

Archivo HTML

Copia lo siguiente en el archivo index.html:

<!-- Detalles completos del proyecto: https://randomnerdtutorials.com/esp32-web-server-websocket-sliders/ -->

<!DOCTYPE html>
<html>
<head>
    <title>ESP IOT DASHBOARD</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/png" href="favicon.png">
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <div class="topnav">
        <h1>Multiple Sliders</h1>
    </div>
    <div class="content">
        <div class="card-grid">
            <div class="card">
                <p class="card-title">Fader 1</p>
                <p class="switch">
                    <input type="range" onchange="updateSliderPWM(this)" id="slider1" min="0" max="100" step="1" value ="0" class="slider">
                </p>
                <p class="state">Brightness: <span id="sliderValue1"></span> &percnt;</p>
            </div>
            <div class="card">
                <p class="card-title"> Fader 2</p>
                <p class="switch">
                    <input type="range" onchange="updateSliderPWM(this)" id="slider2" min="0" max="100" step="1" value ="0" class="slider">
                </p>
                <p class="state">Brightness: <span id="sliderValue2"></span> &percnt;</p>
            </div>
            <div class="card">
                <p class="card-title"> Fader 3</p>
                <p class="switch">
                    <input type="range" onchange="updateSliderPWM(this)" id="slider3" min="0" max="100" step="1" value ="0" class="slider">
                </p>
                <p class="state">Brightness: <span id="sliderValue3"></span> &percnt;</p>
            </div>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

Crear un slider

Las siguientes etiquetas crean la tarjeta para el primer slider (Fader 1):

<div class="card">
  <p class="card-title">Fader 1</p>
  <p class="switch">
    <input type="range" onchange="updateSliderPWM(this)" id="slider1" min="0" max="100" step="1" value ="0" class="slider">
  </p>
  <p class="state">Brightness: <span id="sliderValue1"></span> &percnt;</p>
</div>

El primer párrafo muestra un título para la tarjeta (Fader 1). Puedes cambiar el texto por lo que quieras.

Para crear un slider en HTML se usa la etiqueta <input>. La etiqueta <input> especifica un campo donde el usuario puede introducir datos. Hay una amplia variedad de tipos de input. Para definir un slider, usa el atributo type con el valor range. En un slider, también necesitas definir el rango mínimo y máximo usando los atributos min y max (en este caso, 0 y 100, respectivamente).

También necesitas definir otros atributos como: el atributo step especifica el intervalo entre números válidos. En nuestro caso, lo establecemos a 1. La class para estilizar el slider (class="slider"). El id para poder manipular el valor del slider usando JavaScript (id="slider1"). El atributo onchange para llamar a una función (updateSliderPWM(this)) cuando estableces una nueva posición para el slider. Esta función (definida en el archivo JavaScript) envía el valor actual del slider vía protocolo WebSocket al cliente. La palabra clave this se refiere al elemento HTML del slider.

El slider está dentro de un párrafo con el nombre de clase switch. Así que estas son las etiquetas que realmente crean el slider.

Finalmente, hay un párrafo con una etiqueta <span>, para que podamos insertar el valor actual del slider en ese párrafo refiriéndonos a su id (id="sliderValue1").

Crear más sliders

Para crear más sliders, necesitas copiar todas las etiquetas HTML que crean la tarjeta completa. Sin embargo, primero necesitas considerar que necesitas un id único para cada slider y valor de slider. En nuestro caso, tenemos tres sliders con los siguientes ids: slider1, slider2, slider3, y tres placeholders para el valor del slider con los siguientes ids: sliderValue1, sliderValue2, sliderValue3.

Archivo CSS

Copia lo siguiente en el archivo style.css:

/*  Detalles completos del proyecto: https://randomnerdtutorials.com/esp32-web-server-websocket-sliders/  */

html {
    font-family: Arial, Helvetica, sans-serif;
    display: inline-block;
    text-align: center;
  }
  h1 {
    font-size: 1.8rem;
    color: white;
  }
  p {
    font-size: 1.4rem;
  }
  .topnav {
    overflow: hidden;
    background-color: #0A1128;
  }
  body {
    margin: 0;
  }
  .content {
    padding: 30px;
  }
  .card-grid {
    max-width: 700px;
    margin: 0 auto;
    display: grid;
    grid-gap: 2rem;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  }
  .card {
    background-color: white;
    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
  }
  .card-title {
    font-size: 1.2rem;
    font-weight: bold;
    color: #034078
  }
  .state {
    font-size: 1.2rem;
    color:#1282A2;
  }
  .slider {
    -webkit-appearance: none;
    margin: 0 auto;
    width: 100%;
    height: 15px;
    border-radius: 10px;
    background: #FFD65C;
    outline: none;
  }
  .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: #034078;
    cursor: pointer;
  }
  .slider::-moz-range-thumb {
    width: 30px;
    height: 30px;
    border-radius: 50% ;
    background: #034078;
    cursor: pointer;
  }
  .switch {
    padding-left: 5%;
    padding-right: 5%;
  }

Prefijos de proveedor

Los prefijos de proveedor permiten a un navegador soportar nuevas características CSS antes de que sean completamente soportadas. Los navegadores más comunes usan los siguientes prefijos: -webkit- para Chrome, Safari, versiones más recientes de Opera, casi todos los navegadores iOS; -moz- para Firefox; -o- para versiones antiguas de Opera; -ms- para Microsoft Edge e Internet Explorer.

Los prefijos de proveedor son temporales. Una vez que las propiedades son completamente soportadas por el navegador que usas, ya no los necesitas.

Veamos el selector .slider (estiliza el slider en sí): establecer -webkit-appearance a none anula los estilos CSS por defecto aplicados al slider en Google Chrome, Safari y navegadores Android. Establecer el margen a 0 auto alinea el slider dentro de su contenedor padre. El ancho del slider se establece al 100% y la altura a 15px. El border-radius se establece a 10px. Establece el color de fondo para el slider y establece el outline a none.

Después, formatea el tirador del slider. Usa -webkit- para Chrome, Opera, Safari y Edge y -moz- para Firefox. Establece las propiedades -webkit-appearance y appearance a none para anular las propiedades por defecto. Establece un ancho, alto y border-radius específicos para el tirador. Establecer el mismo ancho y alto con un border-radius del 50% crea un círculo. Después, establece un color para el fondo y establece el cursor a pointer. Siéntete libre de jugar con las propiedades del slider para darle un aspecto diferente.

Archivo JavaScript

Copia lo siguiente en el archivo script.js:

// Detalles completos del proyecto: https://randomnerdtutorials.com/esp32-web-server-websocket-sliders/

var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
window.addEventListener('load', onload);

function onload(event) {
    initWebSocket();
}

function getValues(){
    websocket.send("getValues");
}

function initWebSocket() {
    console.log('Trying to open a WebSocket connection…');
    websocket = new WebSocket(gateway);
    websocket.onopen = onOpen;
    websocket.onclose = onClose;
    websocket.onmessage = onMessage;
}

function onOpen(event) {
    console.log('Connection opened');
    getValues();
}

function onClose(event) {
    console.log('Connection closed');
    setTimeout(initWebSocket, 2000);
}

function updateSliderPWM(element) {
    var sliderNumber = element.id.charAt(element.id.length-1);
    var sliderValue = document.getElementById(element.id).value;
    document.getElementById("sliderValue"+sliderNumber).innerHTML = sliderValue;
    console.log(sliderValue);
    websocket.send(sliderNumber+"s"+sliderValue.toString());
}

function onMessage(event) {
    console.log(event.data);
    var myObj = JSON.parse(event.data);
    var keys = Object.keys(myObj);

    for (var i = 0; i < keys.length; i++){
        var key = keys[i];
        document.getElementById(key).innerHTML = myObj[key];
        document.getElementById("slider"+ (i+1).toString()).value = myObj[key];
    }
}

Aquí tienes una lista de lo que hace este código: inicializa una conexión WebSocket con el servidor, envía un mensaje al servidor para obtener los valores actuales de los sliders, usa la respuesta para actualizar los valores de los sliders en la página web y maneja el intercambio de datos a través del protocolo WebSocket.

El gateway es el punto de entrada a la interfaz WebSocket. window.location.hostname obtiene la dirección de la página actual (la dirección IP del servidor web). Se crea una nueva variable global llamada websocket. Se añade un event listener que llamará a la función onload cuando la página web se cargue.

La función onload() llama a la función initWebSocket() para inicializar una conexión WebSocket con el servidor. La función initWebSocket() inicializa una conexión WebSocket en el gateway definido antes. También asignamos varias funciones de callback para cuando la conexión WebSocket se abre, se cierra o cuando se recibe un mensaje.

Fíjate en que cuando la conexión WebSocket se abre, llamaremos a la función getValues. La función getValues() envía un mensaje al servidor getValues para obtener el valor actual de todos los sliders. Después, debemos manejar qué ocurre cuando recibimos ese mensaje en el lado del servidor (ESP32).

Manejamos los mensajes recibidos vía protocolo WebSocket en la función onMessage(). El servidor envía los estados en formato JSON, por ejemplo:

{
  "sliderValue1": 20,
  "sliderValue2": 50,
  "sliderValue3": 0
}

La función onMessage() simplemente recorre todos los valores y los coloca en los lugares correspondientes de la página HTML.

La función updateSliderPWM() se ejecuta cuando mueves los sliders. Esta función obtiene el valor del slider y actualiza el párrafo correspondiente con el valor correcto. Esta función también envía un mensaje al servidor para que el ESP32 actualice la intensidad del LED. El mensaje se envía en el siguiente formato: slidernumbersslidervalue. Por ejemplo, si mueves el slider número 3 a la posición 40, enviará el siguiente mensaje: 3s40.

Sketch de Arduino

Copia el siguiente código en tu Arduino IDE o en el archivo main.cpp si estás usando PlatformIO:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Detalles completos del proyecto en https://RandomNerdTutorials.com/esp32-web-server-websocket-sliders/
*/
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "LittleFS.h"
#include <Arduino_JSON.h>

// Reemplaza con las credenciales de tu red
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Crea el objeto AsyncWebServer en el puerto 80
AsyncWebServer server(80);
// Crea un objeto WebSocket
AsyncWebSocket ws("/ws");

// Establece los GPIO de los LEDs
const int ledPin1 = 12;
const int ledPin2 = 13;
const int ledPin3 = 14;

String message = "";
String sliderValue1 = "0";
String sliderValue2 = "0";
String sliderValue3 = "0";

int dutyCycle1;
int dutyCycle2;
int dutyCycle3;

// Configuración de las propiedades del PWM
const int freq = 5000;
const int ledChannel1 = 0;
const int ledChannel2 = 1;
const int ledChannel3 = 2;

const int resolution = 8;

// Variable JSON para almacenar los valores de los sliders
JSONVar sliderValues;

// Obtiene los valores de los sliders
String getSliderValues(){
  sliderValues["sliderValue1"] = String(sliderValue1);
  sliderValues["sliderValue2"] = String(sliderValue2);
  sliderValues["sliderValue3"] = String(sliderValue3);

  String jsonString = JSON.stringify(sliderValues);
  return jsonString;
}

// Inicia LittleFS
void initFS() {
  if (!LittleFS.begin()) {
    Serial.println("An error has occurred while mounting LittleFS");
  }
  else{
   Serial.println("LittleFS mounted successfully");
  }
}

// Inicia WiFi
void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
}

void notifyClients(String sliderValues) {
  ws.textAll(sliderValues);
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    message = (char*)data;
    if (message.indexOf("1s") >= 0) {
      sliderValue1 = message.substring(2);
      dutyCycle1 = map(sliderValue1.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle1);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }
    if (message.indexOf("2s") >= 0) {
      sliderValue2 = message.substring(2);
      dutyCycle2 = map(sliderValue2.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle2);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }    
    if (message.indexOf("3s") >= 0) {
      sliderValue3 = message.substring(2);
      dutyCycle3 = map(sliderValue3.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle3);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }
    if (strcmp((char*)data, "getValues") == 0) {
      notifyClients(getSliderValues());
    }
  }
}
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

void setup() {
  Serial.begin(115200);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  initFS();
  initWiFi();

  // Configura los pines LEDC
  ledcAttachChannel(ledPin1, freq, resolution, ledChannel1);
  ledcAttachChannel(ledPin2, freq, resolution, ledChannel2);
  ledcAttachChannel(ledPin3, freq, resolution, ledChannel3);

  initWebSocket();
  
  // URL raíz del servidor web
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/index.html", "text/html");
  });
  
  server.serveStatic("/", LittleFS, "/");

  // Inicia el servidor
  server.begin();
}

void loop() {
  ledcWrite(ledPin1, dutyCycle1);
  ledcWrite(ledPin2, dutyCycle2);
  ledcWrite(ledPin3, dutyCycle3);

  ws.cleanupClients();
}

Cómo funciona el código paso a paso

Veamos las partes relevantes para este proyecto. Para comprender mejor cómo funciona el código, te recomendamos seguir este tutorial sobre el protocolo WebSocket con el ESP32 y este tutorial sobre PWM con el ESP32.

Inserta tus credenciales de red en las siguientes variables para conectar el ESP32 a tu red local.

La función getSliderValues() crea una cadena JSON con los valores actuales de los sliders.

La función notifyClients() notifica a todos los clientes con los valores actuales de los sliders. Llamar a esta función es lo que nos permite notificar cambios en todos los clientes cada vez que estableces una nueva posición para un slider.

La función handleWebSocketMessage(), como su nombre sugiere, maneja qué ocurre cuando el servidor recibe un mensaje del cliente vía protocolo WebSocket. Hemos visto en el archivo JavaScript que el servidor puede recibir el mensaje getValues o un mensaje con el número de slider y el valor del slider. Cuando recibe el mensaje getValues, envía los valores actuales de los sliders.

Si recibe otro mensaje, comprobamos a qué slider corresponde el mensaje y actualizamos el valor del ciclo de trabajo correspondiente. Finalmente, notificamos a todos los clientes que ha ocurrido un cambio.

En el loop(), actualizamos el ciclo de trabajo de los canales PWM para ajustar la intensidad de los LEDs. También llamamos a ws.cleanupClients() para liberar recursos de clientes desconectados.

Subir el código y los archivos

Después de insertar tus credenciales de red, guarda el código. Ve a Programa > Mostrar carpeta del sketch y crea una carpeta llamada data. Dentro de esa carpeta debes guardar los archivos HTML, CSS y JavaScript.

Después, sube el código a tu placa ESP32. Asegúrate de tener la placa y el puerto COM correctos seleccionados. También asegúrate de haber añadido tus credenciales de red.

Después de subir el código, necesitas subir los archivos al sistema de archivos. Pulsa [Ctrl] + [Shift] + [P] en Windows o [⌘] + [Shift] + [P] en macOS para abrir la paleta de comandos. Busca el comando Upload LittleFS to Pico/ESP8266/ESP32 y púlsalo.

Si no tienes esta opción es porque no instalaste el plugin de carga de sistema de archivos.

Importante: asegúrate de que el Monitor Serie esté cerrado antes de subir al sistema de archivos. De lo contrario, la subida fallará.

Cuando todo se haya subido con éxito, abre el Monitor Serie a 115200 baudios. Pulsa el botón EN/RST del ESP32, y debería imprimir la dirección IP del ESP32.

Demostración

Abre un navegador en tu red local y pega la dirección IP del ESP32. Deberías obtener acceso a la página del servidor web para controlar la intensidad de los LEDs.

Mueve los sliders para controlar la intensidad de los LEDs. Abre varias pestañas o conéctate al servidor web usando otro dispositivo, y observa que los valores de los sliders se actualizan casi instantáneamente cada vez que hay un cambio.

Conclusión: lo que has aprendido

En este tutorial, has aprendido cómo construir un servidor web con el ESP32 que sirve una página web con múltiples sliders. Los sliders te permiten controlar la intensidad de LEDs conectados al ESP32. Además, hemos usado el protocolo WebSocket para comunicarnos entre el ESP32 y los clientes.

Este proyecto es la base de cualquier panel de control multipunto que quieras construir con el ESP32. La combinación de WebSocket con múltiples sliders te da una interfaz de usuario tremendamente potente y responsiva, con sincronización en tiempo real entre todos los clientes conectados. Ya sea para controlar la iluminación de una casa, la velocidad de varios motores, o cualquier otro parámetro analógico, este patrón es directamente reutilizable en decenas de proyectos diferentes.

Esperamos que hayas aprendido mucho con este tutorial. Cuéntanos en los comentarios si has seguido con éxito este tutorial y has conseguido que el proyecto funcione.

Vistas: 0

Descubre más desde CIBERED

Suscríbete y recibe las últimas entradas en tu correo electrónico.

Scroll al inicio