Control remoto desde el móvil con Node.js y Socket.io

Sería guay utilizar tu móvil como un control remoto, ¿verdad? Pues aunque pueda parecer difícil, no lo es en absoluto. No necesitas tener conocimiento sobre como desarrollar apps nativas, tu teléfono cuenta con un navegador web bastante válido con soporte para sockets web, lo que te abre un mundo de posibilidades. En este tutorial vamos a utiizar Node.js y Socket.io para gestionar por control remoto una presentación que se ejecute en tu portátil con tu teléfono.

Hay un montón de librerías chulas para presentaciones en HTML5 por la red, y sería una pérdida de tiempo crear esta funcionalidad desde cero. Es por eso que vamos a utilizar Reveal.js, que se encargará de las animaciones y transiciones entre diapositivas, así como el soporte a eventos de teclado y eventos táctiles.

No vamos a crear una interfaz compleja para el control remoto. En su lugar, vamos a sincronizar la presentación que se abrirá en tu smartphone con la que se abrirá en el ordenador utilizando websockets. Esto te permitirá no solo controlar la presentación, sino que también podremos verla a través del teléfono, lo que te ayudará a saber en qué diapositiva te encuentras.

La idea

La técnica que vamos a utilizar es muy sencilla. Reveal.js pondrá el número del slide actual en la url como un hash (por ejemplo, http://ejemplo.com/#1). Enviaremos dicho hash a todos los dispositivos conectados, que harán la transición al nuevo slide automáticamente. Con esto será posible que todos los que abran la URL en un navegador puedan sabotear la presentación, por lo que hará falta que todos los dispositivos introduzcan un código de acceso antes de conectarse.

Vale la pena mencionar que Reveal.js ya cuenta con una API, por lo que podemos utilizarla para sincronizar las dos presentaciones. Pero vamos a seguir con la técnica del hash, que es más simple y funciona con cualquier librería de presentaciones. Así no tendremos problemas de incompatibilidades con cómo hayamos montado nuestra presentación.

Ejecutando el ejemplo

Antes que nada, puedes descargarte el ejemplo desde aquí. Puedes ejecutarlo localmente, o subiéndolo a un hosting con soporte con Node.js. Ejecutarlo en local es mucho más fácil, pero tienes que tener instalado node.js y npm.

Ejecutando el ejemplo localmente

Descarga el código desde aquí
Asegúrate que tienes node.js instalado. Si no lo tienes, instálalo.
Descomprime el archivo y descárgalo en una carpeta
Abre un terminal y haz cd hasta la carpeta
Ejecuta npm install para instalar las librerías específicas
Ejecuta la app.js de node para empezar la presentación
Abre http://localhost:8080 en tu ordenador e introduce el código de acceso (por defecto es “kittens”)
Abre http://laiplocaldetuordenador en tu teléfono e introduce la misma clave de acceso que antes
¡Diviértete!

El código

Pero basta ya de hablar, y vamos a ver el código. Solo hay dos archivos de Javascript, app.js del lado del servidor, y script.js para el navegador. Puedes ejecutar la app en Node.js 0.10+ o en io.js.

Para el backend, utilizamos express y socket.io. Es fundamental estar escuchando y respondiendo los eventos de socket.io. Con express.static, servimos los archivos en la carpeta pública para el mundo. Tenemos un archivo public/index.html que contiene el código para la presentación. Se sirve automáticamente por express.static, por lo no necesitas una ruta /.

app.js

// This is the server-side file of our mobile remote controller app.
// It initializes socket.io and a new express instance.
// Start it by running 'node app.js' from your terminal.


// Creating an express server

var express = require('express'),
	app = express();

// This is needed if the app is run on heroku and other cloud providers:

var port = process.env.PORT || 8080;

// Initialize a new socket.io object. It is bound to 
// the express app, which allows them to coexist.

var io = require('socket.io').listen(app.listen(port));


// App Configuration

// Make the files in the public folder available to the world
app.use(express.static(__dirname + '/public'));


// This is a secret key that prevents others from opening your presentation
// and controlling it. Change it to something that only you know.

var secret = 'kittens';

// Initialize a new socket.io application

var presentation = io.on('connection', function (socket) {

	// A new client has come online. Check the secret key and 
	// emit a "granted" or "denied" message.

	socket.on('load', function(data){

		socket.emit('access', {
			access: (data.key === secret ? "granted" : "denied")
		});

	});

	// Clients send the 'slide-changed' message whenever they navigate to a new slide.

	socket.on('slide-changed', function(data){

		// Check the secret key again

		if(data.key === secret) {

			// Tell all connected clients to navigate to the new slide
			
			presentation.emit('navigate', {
				hash: data.hash
			});
		}
	});
});

console.log('Your presentation is running on http://localhost:' + port);

Y aquí tienes el Javascript para el front-end, que escucha los eventos del cambio de hash y envía mensajes a socket.io al servidor.

public/assets/js/script.js

$(function() {

	// Apply a CSS filter with our blur class (see our assets/css/styles.css)
	
	var blurredElements = $('.homebanner, div.reveal').addClass('blur');

	// Initialize the Reveal.js library with the default config options
	// See more here https://github.com/hakimel/reveal.js#configuration

	Reveal.initialize({
		history: true		// Every slide will change the URL
	});

	// Connect to the socket

	var socket = io();

	// Variable initialization

	var form = $('form.login'),
		secretTextBox = form.find('input[type=text]');

	var key = "", animationTimeout;

	// When the page is loaded it asks you for a key and sends it to the server

	form.submit(function(e){

		e.preventDefault();

		key = secretTextBox.val().trim();

		// If there is a key, send it to the server-side
		// through the socket.io channel with a 'load' event.

		if(key.length) {
			socket.emit('load', {
				key: key
			});
		}

	});

	// The server will either grant or deny access, depending on the secret key

	socket.on('access', function(data){

		// Check if we have "granted" access.
		// If we do, we can continue with the presentation.

		if(data.access === "granted") {

			// Unblur everything
			blurredElements.removeClass('blurred');

			form.hide();

			var ignore = false;

			$(window).on('hashchange', function(){

				// Notify other clients that we have navigated to a new slide
				// by sending the "slide-changed" message to socket.io

				if(ignore){
					// You will learn more about "ignore" in a bit
					return;
				}

				var hash = window.location.hash;

				socket.emit('slide-changed', {
					hash: hash,
					key: key
				});
			});

			socket.on('navigate', function(data){
	
				// Another device has changed its slide. Change it in this browser, too:

				window.location.hash = data.hash;

				// The "ignore" variable stops the hash change from
				// triggering our hashchange handler above and sending
				// us into a never-ending cycle.

				ignore = true;

				setInterval(function () {
					ignore = false;
				},100);

			});

		}
		else {

			// Wrong secret key

			clearTimeout(animationTimeout);

			// Addding the "animation" class triggers the CSS keyframe
			// animation that shakes the text input.

			secretTextBox.addClass('denied animation');
			
			animationTimeout = setTimeout(function(){
				secretTextBox.removeClass('animation');
			}, 1000);

			form.show();
		}

	});

});

Y con esto ya estaría nuestro control remoto desde el móvil con Node.js y Socket.io. Espero que te haya sido de utilidad.

Fuente: tutorialzine.com

COMPARTE ESTE ARTÍCULO

ENVIAR A UN AMIGO
COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN GOOGLE +
¡SÉ EL PRIMERO EN COMENTAR!
Conéctate o Regístrate para dejar tu comentario.