Saltearse al contenido

Unidad 7

Introducción 📜

¿Qué aprenderás en esta unidad? 💡

Actividad 01

Observa funcionando el caso de estudio

👣 Pasos:

  1. Prepara el proyecto:
    • Descarga o clona el código del caso de estudio en tu computador. El código está en este repositorio.
    • Abre una terminal en la carpeta raíz del proyecto.
    • Ejecuta npm install para instalar las dependencias (express, socket.io). Haz esto solo la primera vez.
  2. Inicia el servidor local:
    • Abre la carpeta del proyecto en VS Code.
    • Abre una terminal integrada en VS Code (View > Terminal).
    • En la terminal, ejecuta npm start.
    • Deberías ver el mensaje: Server is listening on http://localhost:3000. ¡Pero aún no accedas a esa URL!
  3. Expón el servidor con Dev Tunnels:
    • Selecciona PORTS. Click en Forward a Port (Dev Tunnels).
    • En el número de puerto, selecciona 3000 (¿Por qué este?)
    • En la columna Visibility, selecciona Public. Esto permitirá que el túnel sea accesible desde cualquier lugar.
    • Copia la URL que aparece en la columna Forwarded Address. Esta URL es la que usarás para acceder al servidor desde tu celular.
    • Envía esta URL a tu celular. Se verá algo como https://TU-TENDRAS-UNA-DIFERNTE.use2.devtunnels.ms/.
  4. Accede a las aplicaciones:
    • En tu Computador: abre un navegador web y ve a la URL: http://localhost:3000/desktop/. Deberías ver el canvas de p5.js con un círculo rojo.
    • En tu Celular: abre un navegador web y ve a la URL que enviaste pero añadiendo /mobile/ al final. Algo así como esto: https://TU-TENDRAS-UNA-DIFERNTE.use2.devtunnels.ms//mobile/ (Asegúrate de añadir /mobile/ al final). Deberías ver el canvas de p5.js con el texto “Touch to move the circle”.
  5. Prueba la interacción:
    • Toca y mueve el dedo sobre la pantalla de tu celular.
    • Observa el navegador de tu computador. El círculo rojo debería moverse siguiendo tu dedo.
    • Observa la terminal donde corre server.js. Deberías ver mensajes “New client connected”, “Received message => …”, y “Client disconnected” cuando cierras las pestañas.
  6. Cierra el Port: una vez termines de hacer las pruebas NO OLVIDES CERRAR el puerto.
  7. ¿Si cerraste el puerto?

🚀 Tu solución:

Actividad 01: Observa funcionando el caso de estudio

URL de Dev Tunnels obtenida

La URL de Dev Tunnels que obtuve fue: https://mi-url-ejemplo.usawdawde2.devtunnels.ms/. Necesitamos usar esta URL en lugar de http://localhost:3000 o la IP local de mi computador porque el túnel expone el servidor local a una dirección accesible desde cualquier lugar, permitiendo que dispositivos fuera de la red local, como mi celular, se conecten a la aplicación.

¿Qué hace npm install y npm start?

  • npm install: Este comando instala todas las dependencias necesarias para el proyecto, como express y socket.io, basándose en las especificaciones del archivo package.json. Lo usamos para asegurarnos de que todas las bibliotecas requeridas estén disponibles para que el servidor funcione correctamente.
  • npm start: Ejecuta el servidor local. Este comando inicia el servidor en el puerto 3000 y permite que la aplicación esté disponible en esa URL. De esta forma, se comienza a escuchar las solicitudes del cliente, y el servidor se mantiene activo para manejar las conexiones entrantes.

Mensajes observados en la terminal del servidor

Al conectar el cliente de escritorio y el cliente móvil, los mensajes que observé en la terminal del servidor fueron:

  • “New client connected”: Este mensaje apareció cuando un cliente (ya sea el de escritorio o móvil) se conectó al servidor.
  • “Received message => …”: Este mensaje se mostró cada vez que el cliente móvil enviaba las coordenadas del toque para mover el círculo. El servidor recibía estas coordenadas y las transmitía a todos los clientes conectados.
  • “Client disconnected”: Este mensaje apareció cuando cerré una de las pestañas del navegador, indicando que el cliente se desconectó.

Los mensajes fueron similares para ambos clientes. El identificador del cliente fue único, lo que permitió al servidor distinguir entre ellos, pero el proceso de conexión y desconexión fue el mismo.

Comportamiento observado

La interacción funcionó correctamente. El círculo en el navegador de mi computadora se movió en tiempo real siguiendo mi dedo sobre la pantalla del celular. La latencia fue mínima, y no noté retrasos significativos. Sin embargo, en algunos momentos hubo una ligera demora al mover el dedo rápidamente sobre la pantalla, pero nada que afectara la experiencia de usuario.

¿Cerraste el puerto?

Sí, cerré el puerto después de completar las pruebas. Es muy importante cerrar el puerto para evitar riesgos de seguridad, ya que tener puertos abiertos innecesariamente puede exponer el sistema a vulnerabilidades. Además, al cerrar el puerto, se liberan los recursos y el servidor ya no queda accesible desde fuera de la red.

Reflexión final

Esta actividad me permitió entender cómo utilizar Dev Tunnels para exponer un servidor local de manera segura a través de una URL pública. Además, me permitió ver cómo funciona la comunicación en tiempo real entre clientes y el servidor usando socket.io, lo cual es fundamental para desarrollar aplicaciones interactivas en tiempo real. La herramienta Dev Tunnels fue esencial para poder conectar dispositivos fuera de la red local, y esta experiencia ha mejorado mi comprensión sobre cómo establecer conexiones de este tipo.

Investigación 🔎

Actividad 02

Conceptos clave: Dev Tunnels, JSON y eventos táctiles

👣 Pasos: (Explicación conceptual)

  1. El problema de la conexión directa:

    • Cuando ejecutas npm start, el servidor escucha en localhost:3000. localhost (o 127.0.0.1) es una dirección especial que siempre se refiere a tu propia máquina.
    • Si intentaras acceder a http://localhost:3000 desde tu celular, este buscaría un servidor en el propio celular, no en tu computador.
    • Podrías usar la IP local de tu computador (ej. 192.168.1.X), pero esto solo funciona si ambos dispositivos están en la misma red Wi-Fi y no hay firewalls bloqueando. No funcionaría si tu celular usa datos móviles o está en otra red.
    • Necesitamos una dirección pública y accesible desde cualquier lugar.
  2. La solución: VS Code Dev Tunnels (Port Forwarding):

    • Dev Tunnels actúa como un intermediario seguro. Crea un túnel desde una URL pública en Internet (la que obtuviste, como https://TU-TENDRAS-UNA-DIFERNTE.use2.devtunnels.ms/) hasta el puerto 3000 de tu localhost.
    • Cuando tu celular (o cualquier cliente en Internet) se conecta a la URL pública de Dev Tunnels, el servicio de Dev Tunnels reenvía esa conexión de forma segura a través del túnel hasta tu servidor Node.js local.
    • Del mismo modo, las respuestas de tu servidor local viajan de vuelta por el túnel hasta el servicio Dev Tunnels, que las entrega al cliente (celular/escritorio).
    • Analogía: Es como tener un número de teléfono público (la URL de Dev Tunnels) que redirige las llamadas a tu teléfono privado en casa (localhost:3000), sin exponer directamente tu número privado.
  3. Enviando datos estructurados: JSON:

    • Queremos enviar más que un simple número o texto. Necesitamos enviar la posición táctil, que tiene coordenadas x e y. Podríamos enviarlos como “120,250”, pero es mejor estructurarlo. Recuerdas los protocolos ASCII y binario de las unidades anteriores?
    • Creamos un objeto JavaScript en el cliente móvil: let touchData = { type: 'touch', x: mouseX, y: mouseY };. Esto es claro y extensible (podríamos añadir más datos en el futuro).
    • Sin embargo, Socket.IO (y muchas comunicaciones en red) envían datos como strings (cadenas de texto). No podemos enviar un objeto JavaScript directamente.
    • JSON.stringify(touchData): Convierte el objeto JavaScript en una cadena de texto con formato JSON. Ejemplo: '{"type":"touch","x":120,"y":250}'. Esta cadena SÍ puede enviarse por la red.
    • JSON.parse(data): En el cliente receptor (escritorio), se recibe la cadena JSON. Esta función la convierte de nuevo en un objeto JavaScript utilizable: { type: 'touch', x: 120, y: 250 }.
  4. Capturando la entrada: eventos táctiles en p5.js (mobile/sketch.js):

    • p5.js ofrece funciones específicas que se ejecutan automáticamente cuando ocurren eventos táctiles en un dispositivo móvil (o simulación en escritorio).
    • touchMoved(): es la función clave aquí. Se llama continuamente mientras el usuario mantiene un dedo presionado y lo mueve sobre el canvas. Dentro de esta función, mouseX y mouseY contienen las coordenadas actuales del toque.
    • Optimización (threshold): el código no envía un mensaje en cada pequeño movimiento detectado por touchMoved(). Comprueba si el movimiento desde la última vez que se envió (lastTouchX, lastTouchY) supera un umbral (threshold). Esto evita inundar la red con mensajes si el dedo tiembla o se mueve mínimamente, enviando solo cambios significativos.
    • Otras funciones útiles (no usadas en este caso base, pero relevantes):
      • touchStarted(): se llama una vez cuando el usuario toca la pantalla por primera vez.
      • touchEnded(): se llama una vez cuando el usuario levanta el dedo de la pantalla.

🚀 Tu solución:

Bitácora - Explicación de los Conceptos Clave en la Comunicación entre el Celular y el Computador

1. ¿Por qué es necesario Dev Tunnels en este escenario y cómo funciona conceptualmente?

Dev Tunnels es necesario en este escenario porque, cuando ejecutamos npm start, el servidor está disponible únicamente en localhost:3000, que solo es accesible desde el propio computador donde está corriendo el servidor. Si intentáramos acceder a esta URL desde el celular, este buscaría un servidor en su propia máquina, no en el computador. Aunque podríamos usar la IP local de la máquina (192.168.X.X), esto solo funcionaría si ambos dispositivos están en la misma red Wi-Fi.

Dev Tunnels actúa como un intermediario que crea un túnel entre el servidor local y una URL pública en Internet. La URL pública se convierte en un punto de acceso accesible desde cualquier lugar. Cuando el celular se conecta a esta URL, el servicio de Dev Tunnels redirige la conexión de manera segura hacia el puerto del servidor local, permitiendo que el celular y el computador se comuniquen.

Analogía: Es como tener un número de teléfono público que redirige las llamadas a tu teléfono privado sin exponer directamente tu número privado.

2. ¿Por qué usamos JSON.stringify() en el emisor (móvil) y JSON.parse() en el receptor (escritorio)? ¿Qué problema resuelve JSON aquí?

El motivo por el cual utilizamos JSON.stringify() en el emisor (móvil) y JSON.parse() en el receptor (escritorio) es que los datos deben ser enviados como cadenas de texto (strings) a través de la red, ya que los protocolos de comunicación no permiten transmitir objetos JavaScript directamente.

  • JSON.stringify() convierte un objeto JavaScript (como { type: 'touch', x: 120, y: 250 }) en una cadena de texto que puede ser enviada por la red.
  • JSON.parse() se utiliza en el receptor para convertir la cadena JSON de vuelta en un objeto JavaScript utilizable.

Esto resuelve el problema de enviar datos complejos (como las coordenadas de un toque) de manera eficiente y estructurada, sin perder la integridad de la información. Además, permite que los datos sean fácilmente intercambiables entre diferentes lenguajes y plataformas que entienden el formato JSON.

3. Describe la función de touchMoved() y por qué se usa la variable threshold en el cliente móvil.

La función touchMoved() en p5.js es llamada repetidamente mientras el usuario mantiene el dedo presionado y lo mueve sobre la pantalla. Dentro de esta función, las variables mouseX y mouseY contienen las coordenadas del toque, lo que permite saber en tiempo real la posición del dedo en la pantalla.

La variable threshold se utiliza para evitar que se envíen mensajes cada vez que el dedo se mueve un poco, lo cual podría generar una gran cantidad de datos innecesarios. El código solo envía las coordenadas del toque si el movimiento supera un umbral predefinido (threshold), asegurando que solo los movimientos significativos se transmitan. Esto ayuda a reducir la latencia y la carga en la red, mejorando el rendimiento general.

4. ¿Qué otros eventos táctiles existen en p5.js y para qué tipo de interacciones podrían ser útiles (ej. un botón virtual, detectar un tap)?

En p5.js existen otros eventos táctiles útiles para interactuar con la pantalla táctil de un dispositivo. Algunos de estos eventos incluyen:

  • touchStarted(): Se llama cuando el usuario toca la pantalla por primera vez. Puede ser útil para detectar la acción inicial de un usuario, como cuando se presiona un botón virtual.
  • touchEnded(): Se llama cuando el usuario levanta el dedo de la pantalla. Esto podría utilizarse para finalizar una acción, como soltar un objeto o confirmar una selección.
  • touchMoved(): Ya explicado, se utiliza para detectar el movimiento del dedo.
  • touches[]: Esta función proporciona información sobre todos los toques activos en la pantalla. Esto es útil cuando se detectan múltiples toques (por ejemplo, en un juego de dos jugadores).

Estos eventos podrían ser útiles en aplicaciones donde se requiera un control preciso del dedo, como juegos móviles o interfaces de usuario con botones virtuales.

5. Compara brevemente Dev Tunnels con simplemente usar la IP local. ¿Cuáles son las ventajas y desventajas de cada uno?

Ventajas de usar Dev Tunnels:

  • Accesibilidad global: Permite que el servidor sea accesible desde cualquier lugar, incluso si el celular está fuera de la red local, o si está usando datos móviles en lugar de Wi-Fi.
  • Seguridad: Dev Tunnels proporciona un túnel seguro, evitando exponer directamente la IP local del servidor a posibles amenazas externas.
  • Facilidad de configuración: No necesitas configurar redes o firewalls. Solo creas el túnel desde VS Code.

Desventajas de usar Dev Tunnels:

  • Dependencia de una herramienta externa: Si Dev Tunnels experimenta problemas o es inaccesible, no podrás usar el túnel.
  • Posible latencia: Dependiendo de la calidad de la conexión a Internet, el túnel puede introducir algo de latencia en la comunicación.

Ventajas de usar la IP local:

  • Conexión directa y rápida: No depende de servicios externos. Si ambos dispositivos están en la misma red, la comunicación es más rápida.
  • Control total: Tienes control completo sobre la red y la configuración del servidor.

Desventajas de usar la IP local:

  • Limitación a la misma red: Solo funciona si ambos dispositivos están conectados a la misma red local, lo que limita su uso a entornos específicos.
  • Problemas de seguridad: Exponer la IP local puede ser riesgoso, especialmente si no se toman medidas adecuadas para protegerla.

Conclusión

Esta unidad me ayudó a entender cómo manejar la comunicación entre dispositivos usando herramientas como Dev Tunnels y protocolos como JSON. También aprendí sobre los eventos táctiles en p5.js y cómo optimizar la comunicación enviando solo los cambios significativos en los movimientos táctiles.

Actividad 03

Análisis del servidor puente (server.js)

👣 Pasos: (Análisis del código)

server.js
const express = require('express'); // Framework para servidor web
const http = require('http'); // Módulo HTTP base de Node.js
const socketIO = require('socket.io'); // Librería para WebSockets
const app = express(); // Crea la aplicación Express
const server = http.createServer(app); // Crea el servidor HTTP usando Express
const io = socketIO(server); // Vincula Socket.IO al servidor HTTP
const port = 3000; // Puerto en el que escuchará LOCALMENTE
// Sirve archivos estáticos desde la carpeta 'public'
app.use(express.static('public'));
// Evento: se dispara cuando un nuevo cliente (navegador) se conecta vía Socket.IO
io.on('connection', (socket) => {
console.log('New client connected - ID:', socket.id);
// Evento: se dispara cuando ESE cliente envía un mensaje llamado 'message'
socket.on('message', (message) => {
console.log(`Received message => ${message} from ID: ${socket.id}`);
// Retransmite el mensaje recibido a TODOS los OTROS clientes conectados
socket.broadcast.emit('message', message);
});
// Evento: se dispara cuando ESE cliente se desconecta
socket.on('disconnect', () => {
console.log('Client disconnected - ID:', socket.id);
});
});
// Inicia el servidor y lo pone a escuchar en el puerto local especificado
server.listen(port, () => {
console.log(`Server is listening on http://localhost:${port}`);
});

🚀 Tu solución:

Análisis del servidor server.js

1. Función principal de express.static('public')

La función express.static('public') en este servidor se encarga de servir archivos estáticos desde la carpeta public cuando un navegador hace una solicitud. Esto significa que los archivos como HTML, CSS, JavaScript, imágenes, etc., serán buscados automáticamente dentro de la carpeta public y enviados directamente como respuesta a las solicitudes. Esto simplifica el manejo de archivos estáticos, evitando la necesidad de definir rutas específicas para cada archivo como se hacía en la Unidad 6 con app.get('/ruta', ...).

En comparación con el uso de app.get('/ruta', ...) en la Unidad 6, donde definías explícitamente cada ruta y archivo que querías servir, express.static es una forma más automática y eficiente de manejar archivos estáticos, ya que no necesitas definir cada ruta de manera manual.

2. Flujo de un mensaje táctil

  1. Evento que envía el mensaje desde el móvil: El cliente móvil captura el movimiento táctil utilizando el evento touchMoved() de p5.js. Dentro de este evento, se obtiene la posición actual del toque, que se estructura en un objeto JavaScript (let touchData = { type: 'touch', x: mouseX, y: mouseY };).

  2. Evento que recibe el servidor: El servidor recibe este mensaje a través de un evento socket.on('message', (message) => {...}) en el servidor. Aquí, el servidor escucha cualquier mensaje que se envíe desde el cliente móvil. El mensaje recibido contiene los datos estructurados en formato JSON (como { type: 'touch', x: 120, y: 250 }).

  3. Acción del servidor con el mensaje: El servidor, al recibir el mensaje, lo retransmite a todos los demás clientes conectados, pero no al cliente que envió el mensaje. Esto se hace con socket.broadcast.emit('message', message);. El uso de broadcast.emit asegura que el mensaje no se reenvíe al mismo cliente que lo originó.

  4. Evento que envía el servidor al escritorio: El mensaje es reenviado a todos los demás clientes conectados (en este caso, el cliente de escritorio), mediante el evento socket.broadcast.emit('message', message);. Este evento garantiza que el cliente de escritorio reciba los mismos datos del toque que fueron enviados desde el móvil.

  5. Uso de socket.broadcast.emit en lugar de io.emit o socket.emit: Se utiliza socket.broadcast.emit en este caso porque queremos enviar el mensaje a todos los demás clientes conectados, pero no al cliente que lo originó. Usar socket.emit enviaría el mensaje solo al cliente que lo originó, mientras que io.emit enviaría el mensaje a todos los clientes, incluyendo al que lo originó. El uso de broadcast.emit garantiza que solo los otros clientes reciban el mensaje, no el móvil que lo envió.

3. ¿Qué pasaría si conectaras dos computadores de escritorio y un móvil?

Si conectas dos computadores de escritorio y un móvil al servidor, y mueves el dedo en el móvil, el flujo sería el siguiente:

  • El móvil envía un mensaje de tipo message con los datos del toque al servidor.
  • El servidor recibe este mensaje y lo retransmite a todos los demás clientes conectados usando socket.broadcast.emit. Esto significa que:
    • El primer computador de escritorio recibirá el mensaje.
    • El segundo computador de escritorio también recibirá el mensaje.
    • El móvil no recibirá el mensaje porque fue el que lo originó, gracias al uso de broadcast.

Por lo tanto, los dos computadores de escritorio recibirían el mensaje del toque, pero el móvil que originó el mensaje no lo recibiría.

4. ¿Qué información útil proporcionan los mensajes console.log en el servidor durante la ejecución?

Los mensajes console.log son útiles para monitorear y depurar el servidor, ya que proporcionan información sobre:

  • Conexiones de clientes: Cada vez que un cliente se conecta, se muestra un mensaje con su socket.id único. Esto ayuda a identificar cuántos clientes están conectados y a rastrear eventos relacionados con cada cliente.

    Ejemplo: console.log('New client connected - ID:', socket.id);

  • Recepción de mensajes: Cuando un cliente envía un mensaje (como el toque desde el móvil), el servidor imprime el mensaje recibido y el socket.id del cliente que lo envió. Esto ayuda a verificar que el servidor está recibiendo los mensajes correctamente.

    Ejemplo: console.log(Received message => {socket.id});

  • Desconexión de clientes: Cuando un cliente se desconecta, se muestra un mensaje en la consola con su socket.id. Esto ayuda a verificar cuándo y quién se ha desconectado del servidor.

    Ejemplo: console.log('Client disconnected - ID:', socket.id);

Resumen de Respuestas

  • express.static('public') sirve para gestionar archivos estáticos de manera automática, mientras que app.get() requeriría definir rutas manualmente.
  • El flujo de un mensaje táctil pasa por el móvil capturando el evento, enviándolo al servidor, y retransmitiéndolo a los otros clientes (excepto al que lo envió).
  • El uso de socket.broadcast.emit asegura que el mensaje no se envíe al cliente que lo originó, sino a todos los demás.
  • En un escenario con dos escritorios y un móvil, los escritorios recibirían el mensaje, pero el móvil no.
  • Los console.log ayudan a monitorear las conexiones, los mensajes recibidos y las desconexiones de los clientes.

Actividad 04

Análisis del cliente móvil (mobile/sketch.js) y de escritorio (desktop/sketch.js)

👣 Pasos: (Análisis del código)

1. Cliente móvil (mobile/sketch.js) - El Emisor
// mobile/sketch.js (partes clave)
let socket;
let lastTouchX = null;
let lastTouchY = null;
const threshold = 5; // Umbral para evitar enviar demasiados mensajes
function setup() {
// ... createCanvas, background ...
socket = io();
socket.on('connect', () => console.log('Connected to server'));
// ... otros listeners de socket ('message', 'disconnect', 'connect_error') ...
}
function touchMoved() { // Función especial de p5.js para eventos táctiles
if (socket && socket.connected) {
// Calcula si el movimiento supera el umbral
let dx = abs(mouseX - lastTouchX);
let dy = abs(mouseY - lastTouchY);
if (dx > threshold || dy > threshold || lastTouchX === null) { // Enviar si supera umbral o es el primer toque
let touchData = {
type: 'touch', // Tipo de mensaje (podríamos tener otros)
x: mouseX, // Coordenada X del toque (relativa al canvas móvil)
y: mouseY // Coordenada Y del toque
};
// Envía el objeto como una cadena JSON al servidor
socket.emit('message', JSON.stringify(touchData));
// Actualiza la última posición registrada
lastTouchX = mouseX;
lastTouchY = mouseY;
}
}
return false; // Evita comportamiento default del navegador en móviles
}
2. Cliente de Escritorio (desktop/sketch.js) - El Receptor
// desktop/sketch.js (partes clave)
let socket;
let circleX = 200; // Posición inicial X
let circleY = 200; // Posición inicial Y
function setup() {
// ... createCanvas, background ...
socket = io();
socket.on('connect', () => console.log('Connected to server'));
// Listener clave: se ejecuta cuando llega un mensaje del servidor
socket.on('message', (data) => {
console.log(`Received message: ${data}`);
try {
// Intenta convertir la cadena JSON de vuelta a un objeto
let parsedData = JSON.parse(data);
// Verifica si es un mensaje de tipo 'touch'
if (parsedData && parsedData.type === 'touch') {
// Actualiza las coordenadas del círculo con los datos recibidos
// ¡Ojo! Las coordenadas vienen del canvas móvil.
// Aquí simplemente las usamos, pero en un caso real podríamos necesitar mapearlas
// si los canvas tuvieran tamaños diferentes.
circleX = parsedData.x;
circleY = parsedData.y;
}
} catch (e) {
console.error("Error parsing received JSON:", e);
}
});
// ... otros listeners ('disconnect', 'connect_error') ...
}
function draw() {
background(220);
fill(255, 0, 0);
ellipse(circleX, circleY, 50, 50); // Dibuja el círculo en la posición actualizada
}

🚀 Tu solución:

Análisis del Cliente Móvil y de Escritorio

Propósito de mobile/sketch.js y desktop/sketch.js

El propósito principal de mobile/sketch.js es capturar los toques del usuario en un dispositivo móvil (como un smartphone o tablet) y enviar esos datos de posición (coordenadas x e y) al servidor a través de Socket.IO. Esto se logra utilizando la función touchMoved() de p5.js, que detecta el movimiento del dedo sobre el canvas.

Por otro lado, desktop/sketch.js es responsable de recibir esos datos desde el servidor, interpretar las coordenadas del toque (en formato JSON) y actualizar la posición de un círculo en el canvas del cliente de escritorio. El círculo se mueve en función de las coordenadas recibidas, lo que simula la interacción entre el dispositivo móvil y el escritorio.

Cliente Móvil (mobile/sketch.js)

Explicación del Código (Móvil)

let socket;
let lastTouchX = null;
let lastTouchY = null;
const threshold = 5; // Umbral para evitar enviar demasiados mensajes
function setup() {
socket = io();
socket.on('connect', () => console.log('Connected to server'));
}
function touchMoved() {
if (socket && socket.connected) {
let dx = abs(mouseX - lastTouchX);
let dy = abs(mouseY - lastTouchY);
if (dx > threshold || dy > threshold || lastTouchX === null) {
let touchData = {
type: 'touch', // Tipo de mensaje
x: mouseX, // Coordenada X del toque
y: mouseY // Coordenada Y del toque
};
socket.emit('message', JSON.stringify(touchData));
lastTouchX = mouseX;
lastTouchY = mouseY;
}
}
return false; // Evita comportamiento por defecto del navegador en móviles
}

Aplicación 🛠

Actividad 05

Aplica lo aprendido

👣 Pasos:

  1. Analiza la siguiente aplicación:
let particles = [];
function setup() {
createCanvas(windowWidth, windowHeight);
background(0, 20);
}
function draw() {
if (mouseIsPressed) {
particles.push(new Particle(mouseX, mouseY));
}
for (let i = particles.length - 1; i >= 0; i--) {
particles[i].update();
particles[i].display();
if (particles[i].isDead()) {
particles.splice(i, 1);
}
}
if (particles.length === 0) background(0, 20);
}
class Particle {
constructor(x, y) {
this.pos = createVector(x, y);
this.vel = p5.Vector.random2D();
this.lifespan = 255;
this.size = random(5, 20);
this.noiseOffset = random(1000);
}
update() {
// Se utiliza ruido Perlin para definir la dirección de la fuerza
let angle =
noise(this.pos.x * 0.005, this.pos.y * 0.005, this.noiseOffset) *
TWO_PI *
2;
let force = p5.Vector.fromAngle(angle);
force.mult(0.5);
// Se aplica la fuerza a la velocidad
this.vel.add(force);
this.vel.limit(4);
this.pos.add(this.vel);
// La vida de la partícula disminuye gradualmente
this.lifespan -= 3;
}
display() {
fill(150, 100, 255, this.lifespan);
ellipse(this.pos.x, this.pos.y, this.size);
}
isDead() {
return this.lifespan < 0;
}
}
function keyPressed() {
console.log(`particle size: ${particles.length}`);
}
  1. Vas a modificar la aplicación anterior para que se convierta en la aplicación de escritorio.

    • El móvil enviará la posición del toque (X/Y) al servidor.
    • El escritorio recibirá la posición y dibujará una partícula en esa posición.
    • La partícula se comportará como en el código original, pero ahora su posición inicial será la del toque del móvil.
    • El móvil enviará el color y si las partículas se pintan o no con stroke.
  2. Ten presente que la aplicación móvil enviará la posición del toque (X/Y), el color de la partícula y si se pinta o no con stroke. El escritorio recibirá estos datos y los usará para dibujar la partícula en la posición del toque.

📝 Actividad pendiente por iniciar

El archivo student.md está vacío

Consolidación y metacognición 🤔

Actividad 06

Consolidación de lo aprendido

👣 Pasos:

  1. Identifica los componentes clave: lista todos los elementos principales involucrados en la comunicación:
    • Aplicación cliente móvil (navegador + mobile/sketch.js)
    • Servidor Node.js (server.js + Express + Socket.IO)
    • Servicio de VS Code Dev Tunnels (actuando como proxy/puente público)
    • Aplicación cliente de escritorio (navegador + desktop/sketch.js)
    • El usuario (interactuando con el móvil)
  2. Dibuja el diagrama:
    • Representa cada componente como una caja o nodo en tu diagrama.
    • Usa flechas para indicar el flujo de la información principal (el evento de toque, color, stroke).
    • Etiqueta las flechas para indicar qué tipo de información o evento representan en cada paso (ej: “Evento touch (x, y)”, “socket.emit(‘message’, JSON)”, “Petición HTTP/WebSocket”, “socket.broadcast.emit(‘message’, JSON)”, “Actualización de coordenadas”, “Dibujo en canvas”).
    • Asegúrate de mostrar claramente cómo interviene el servicio Dev Tunnels entre internet y tu servidor local.
  3. Añade explicaciones: debajo o al lado del diagrama, escribe una breve descripción del rol de cada componente principal en el proceso general.

🚀 Tu solución:

Consolidación de lo Aprendido Diagrama del Sistema Completo A continuación, se presenta el diagrama que ilustra todos los componentes y el flujo de información desde el toque en el móvil, la selección de color y definición de stroke, hasta la actualización visual en el escritorio:

Descripciones de los Componentes y sus Roles

  1. Aplicación Cliente Móvil (mobile/sketch.js) Rol: Este componente captura los eventos táctiles del usuario en el móvil, detectando el movimiento del toque. Cuando el usuario mueve el dedo, el móvil envía la información de la posición del toque al servidor. Se utiliza el umbral (threshold) para evitar enviar demasiados mensajes si el toque se mueve solo ligeramente.

Flujo de Información:

El evento touchMoved() captura el toque y envía las coordenadas al servidor a través de un socket.emit(‘message’, JSON).

  1. Servidor Node.js (server.js + Express + Socket.IO) Rol: El servidor actúa como intermediario entre el cliente móvil y el cliente de escritorio. Recibe los datos del toque del móvil y los transmite a los clientes de escritorio conectados.

Flujo de Información:

El servidor escucha el evento message desde el cliente móvil.

Una vez que recibe el mensaje, lo transmite a todos los clientes conectados utilizando socket.broadcast.emit(‘message’, JSON), asegurándose de que todos los clientes vean el mismo movimiento del toque.

  1. Servicio de VS Code Dev Tunnels Rol: Este servicio actúa como un puente entre el servidor local y el mundo exterior. Permite que los dispositivos móviles (que se encuentran en una red diferente) puedan comunicarse con el servidor local, actuando como un proxy para la conexión.

Flujo de Información:

El servicio establece una conexión segura entre el servidor Node.js y los clientes que se encuentran fuera de la red local, facilitando la comunicación a través de Internet.

  1. Aplicación Cliente de Escritorio (desktop/sketch.js) Rol: Este componente recibe los datos del servidor y actualiza la posición visual del círculo en el canvas del escritorio en función de las coordenadas enviadas desde el móvil.

Flujo de Información:

El cliente escucha el evento message usando socket.on(‘message’, …).

Luego procesa la información (JSON) y actualiza las coordenadas del círculo en el canvas, reflejando el movimiento del toque del móvil.

  1. El Usuario (Interacción con el Móvil) Rol: El usuario interactúa con la aplicación móvil tocando la pantalla, moviendo el dedo para generar eventos de toque. Estas interacciones desencadenan el flujo de información que se transmite al servidor y, posteriormente, al cliente de escritorio.

Reflexión Final ¿Reflejan con precisión cómo funciona el sistema de la fase de aplicación? Sí, el diagrama y las explicaciones proporcionan una visión clara del flujo de la información en el sistema, desde el momento en que el usuario toca la pantalla en el móvil hasta la actualización visual del cliente de escritorio.

¿Hay algún paso o componente que aún no te quede claro? No, todos los pasos y componentes están claros en cuanto a su rol y flujo de información. Sin embargo, podría ser útil explorar más a fondo cómo se manejan los eventos en tiempo real si la latencia o el rendimiento del servidor se convierten en un problema.

Actividad 07

Autoevaluación: ¿Qué he aprendido?

👣 Pasos:

  1. Revisa los objetivos: vuelve a leer la sección ¿Qué aprenderás en esta unidad? 💡.
  2. Evalúa tu confianza: para cada objetivo de aprendizaje, evalúate honestamente usando una escala simple (ej: 2=Necesito repasar mucho, 3=Lo entiendo pero con dudas, 4=Lo entiendo bien, 5=Podría explicarlo a un compañero).
    • Configurar y usar VS Code Dev Tunnels: [Tu Puntuación]
    • Implementar arquitectura cliente-servidor (móvil->servidor): [Tu Puntuación]
    • Usar Socket.IO para retransmitir datos (servidor->escritorio): [Tu Puntuación]
    • Capturar y procesar eventos en el móvil (p5.js): [Tu Puntuación]
    • Modificar sistema interactivo para crear la experiencia: [Tu Puntuación]
    • Analizar y explicar flujo de datos completo (móvil->servidor->escritorio): [Tu Puntuación]
  3. Reflexiona sobre el proceso:
    • ¿Qué concepto o actividad de esta unidad te resultó más fácil de entender o realizar? ¿Por qué crees que fue así?
    • ¿Qué concepto o actividad te presentó mayor dificultad? ¿Qué pasos seguiste para intentar superarla? ¿Qué recursos o estrategias te fueron más útiles?
    • Describe con tus propias palabras, como si se lo explicaras a alguien que no tomó el curso, cuál es el flujo principal de información en la aplicación que construimos (desde la interacción del usuario en el móvil hasta la imagen en el escritorio). ¿Qué rol juega cada tecnología (Node.js, Socket.IO, Dev Tunnels, p5.js)?
    • ¿Cómo crees que podrías aplicar lo aprendido en esta unidad (usar un móvil como controlador, comunicación en tiempo real, túneles) en otros proyectos o contextos?

📝 Actividad pendiente por iniciar

El archivo student.md está vacío

Actividad 08

Mejorando juntos: feedback de la unidad

👣 Pasos:

  1. Reflexiona sobre la unidad en general: piensa en todo el proceso, desde la introducción hasta la consolidación.
  2. Considera los siguientes aspectos y proporciona comentarios específicos para cada uno:
    • Claridad de los objetivos: ¿Fueron claros los objetivos de aprendizaje desde el principio? ¿Sientes que los alcanzaste?
    • Caso de estudio: ¿Fue útil el caso de estudio proporcionado? ¿Fue demasiado simple, demasiado complejo o adecuado?
    • Conceptos nuevos (Dev Tunnels): ¿Fue clara la explicación y la necesidad de usar Dev Tunnels? ¿Tuviste dificultades con su configuración o uso?
    • Análisis del código (SEEK): ¿Fueron útiles las explicaciones detalladas del código del servidor y los clientes? ¿Los experimentos propuestos te ayudaron a entender mejor? ¿Algo fue confuso?
    • Actividad de aplicación (APPLY): ¿Te pareció interesante y motivadora la actividad de modificar la interacción? ¿Fue un reto adecuado?
    • Actividades de reflexión (REFLECT): ¿Te ayudaron las actividades de consolidación y autoevaluación a reforzar tu aprendizaje?
    • Ritmo y carga de trabajo: ¿Cómo te pareció el ritmo de la unidad? ¿La cantidad de trabajo fue razonable?
    • Recursos: ¿Fueron útiles los enlaces y recursos proporcionados? ¿Echaste en falta algún recurso adicional?
  3. Sugerencias de mejora: ¿Tienes alguna sugerencia específica sobre cómo se podría mejorar esta unidad? (Ej: más ejemplos, explicaciones alternativas, diferentes tipos de actividades, etc.)
  4. Comentario general: cualquier otro comentario o aspecto que quieras destacar sobre tu experiencia en esta unidad.

🚀 Tu solución:

Feedback sobre la Unidad 7

1. Claridad de los Objetivos

  • Comentario: Los objetivos de aprendizaje fueron bastante claros desde el principio. En cada actividad se comprendía el propósito de lo que se quería lograr, especialmente con respecto al uso de Node.js, los WebSockets, y la interacción entre el cliente móvil y el escritorio. Siento que he alcanzado los objetivos, ya que pude implementar correctamente la interacción entre los dispositivos y comprender el flujo de datos.

2. Caso de Estudio

  • Comentario: El caso de estudio proporcionado fue útil y adecuado en términos de complejidad. No fue ni demasiado simple ni demasiado complejo. Me permitió entender cómo conectar diferentes tecnologías y servicios (como el servidor y los túneles), y cómo trabajar con ellos de manera práctica. Sin embargo, me hubiera gustado que hubiera más ejemplos prácticos sobre la comunicación en tiempo real y cómo manejar posibles errores de conexión.

3. Conceptos Nuevos (Dev Tunnels)

  • Comentario: La explicación sobre los Dev Tunnels fue clara y me permitió comprender su función como puente para la comunicación entre el servidor local y los clientes. No tuve mayores dificultades para configurarlo, aunque al principio me costó entender por qué era necesario usar un servicio externo para algo tan simple. Una vez comprendí su papel, todo fue más claro, pero una demostración paso a paso de la configuración podría haber sido útil para evitar cualquier confusión.

4. Análisis del Código (SEEK)

  • Comentario: Las explicaciones detalladas del código del servidor y los clientes fueron muy útiles. El análisis me permitió entender cómo funcionan los WebSockets y cómo se gestionan los eventos en tiempo real. Los experimentos propuestos me ayudaron a practicar y a profundizar en el manejo de los eventos de la aplicación. No encontré confusión, aunque una mayor profundización en los posibles errores comunes o soluciones ante problemas de conectividad podría haber sido beneficiosa.

5. Actividad de Aplicación (APPLY)

  • Comentario: La actividad de modificar la interacción fue interesante y motivadora. Modificar la interacción del usuario fue un reto adecuado, ya que no solo puse en práctica los conceptos aprendidos, sino que también experimenté con la personalización de la interfaz. Me gustó que fuera una tarea abierta con espacio para creatividad, lo que hizo la experiencia más interesante. Quizás un reto adicional sobre la optimización de rendimiento en tiempo real habría sido un desafío interesante.

6. Actividades de Reflexión (REFLECT)

  • Comentario: Las actividades de consolidación y autoevaluación fueron muy útiles para reforzar lo aprendido. Me ayudaron a revisar el contenido y asegurarme de que comprendía todo el proceso de la unidad. Sin embargo, algunas de las preguntas de reflexión podrían haberse enfocado más en los aspectos técnicos específicos, como el manejo de conexiones en tiempo real y los posibles problemas de latencia.

7. Ritmo y Carga de Trabajo

  • Comentario: El ritmo de la unidad fue adecuado y la carga de trabajo razonable. No me sentí abrumado, pero tampoco fue una unidad demasiado fácil. Los pasos fueron bien distribuidos y me dieron suficiente tiempo para experimentar y entender cada componente antes de pasar al siguiente. Fue un buen equilibrio entre teoría y práctica.

8. Recursos

  • Comentario: Los enlaces y recursos proporcionados fueron útiles, especialmente los ejemplos de código y la documentación de Socket.IO. Sin embargo, algunos recursos adicionales sobre las mejores prácticas para trabajar con WebSockets en producción (como manejo de errores o optimización de la comunicación) podrían haber complementado bien los materiales de esta unidad.

9. Sugerencias de Mejora

  • Comentario:
    1. Más ejemplos sobre la optimización de la comunicación en tiempo real y la gestión de errores de conexión.
    2. Incluir más casos de uso donde los WebSockets puedan ser útiles en aplicaciones más complejas.
    3. Incluir ejercicios sobre cómo manejar múltiples conexiones y usuarios simultáneos.

10. Comentario General

  • Comentario: En general, la unidad fue muy útil para aprender a implementar la comunicación en tiempo real entre clientes y servidores. El enfoque práctico me permitió aplicar los conceptos rápidamente y experimentar con ellos. La estructura de la unidad, con actividades claras y recursos útiles, hizo que el proceso de aprendizaje fuera fluido. Aprecio mucho la oportunidad de trabajar con tecnologías como Node.js, Socket.IO y Dev Tunnels, ya que es una combinación poderosa para proyectos en tiempo real.