Aujourd’hui, je souhaite vous faire partager une petite expérience rapide avec Node.js et socket.io pour faire du temps réel Smartphone - PC.

L’idée de base est de faire communiquer son Smartphone avec son Ordinateur avec du Node.js. Jusque là pour ceux qui ont déjà essayé cette technologie, ça va. Si ce n’est pas le cas, pas de soucis, on y viendra ;)

La différence qu’il y aura dans notre application avec un simple Chat ou un temps réel classique, c’est que nous allons nous servir de notre Smartphone pour “piloter” notre Ordinateur, ça sonne classe non ?

Introduction

Pour les novices en Node.js, voilà ce qu’il faut savoir :

Node.js est une technologie :

  • Javascript
  • Qui s’éxécute côté serveur (comme le PHP)
  • Qui permet du temps réel très facilement (grâce aux websockets et socket.io par exemple)
  • De bas niveau, c’est à dire qu’on doit créer nous-même le serveur http (pas de panique, ça prend 2 lignes)

Je compte me servir du Framework Express dans ce tutoriel, qui permet de passer outre toute la “complexité” de la création du serveur. Pour ceux qui souhaitent découvrir Node.js à la base avant de commencer ce tutoriel, vous avez l’excellent (comme toujours) cours d’OpenClassrooms ou bien une très bonne introduction par Developpez.com.

La mise en place de l’environnement

Nous allons donc commencer par le début, à savoir créer nos fichiers. Voici l’arborescence que vous devrez avoir :

public
    css
        styles.css
    js
        main.js
app.js
template
    home.ejs

Une fois cette arborescence faite, nous pouvons commencer à installer les outils.

Pour ceux qui ont déjà Node.js et npm d’installés sur leur machine, vous pouvez passer au début du codage

Pour les autres, il va falloir installer Node.js, qui est désormais livré avec la commande NPM.

Je vous invite à aller sur le Site officiel pour télécharger et installer Node.js. Une fois que vous aurez fait toutes les étapes et que vous aurez des réponses cohérentes en tapant “npm” dans votre console, vous pourrez passer à la suite ;) (désolé de ne pas expliquer comment l’installer en détails, mais ce n’est pas vraiment l’objectif du tutoriel)

Les premières lignes de code

.js est présent sur la machine, la commande npm marche, everything is ok.

Nous allons pouvoir commencer à mettre en place le serveur Node dans le fichier app.js.

Effectuez tout d’abord la commande “npm init” en étant à la racine de votre dossier, appuyez sur entrée à chaque fois jusqu’à la création du fichier package.json.

Une fois ceci fait, vous pouvez écrire votre premier commande dans votre console.

npm install express

Express étant installé, le code va pouvoir enfin vraiment commencer, voici les premières lignes à entrer.

var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
var server = app.listen(1818);

4 lignes pour créer un serveur et le faire marcher avec Node.js et Express. La troisième ne compte même pas, donc 3 lignes, sympa non ?

Pour décortiquer un peu, après avoir installer express avec la commande npm, on l’inclut dans notre javascript avec le require(‘express’);

On le met ensuite dans une variable qui va définir notre application. Le préfixe app va donc être utiliser pour chaque action souhaitant être effectué sur le serveur (comme le dossier cible défini ci-dessus, le dossier “public” dans notre cas)

Pour finir, on “écoute” le serveur sur le port 1818. Tous les ports du monde (en 4 chiffres je crois) peuvent marcher, vous pouvez essayer 8080, 8888, 1000, bref, tout marche.

Notre serveur est maintenant mis en place, on va passer au HTML.

Vue et templating EJS

Pour l’HTML, on va commencer par ce que tout bon document devrait avoir au minimum

<!DOCTYPE HTML>
<html lang="fr">
    <head>
        <title>Remote Control</title>
        <meta charset="utf-8" />
    </head>

    <body>
    </body>
</html>

Maintenant qu’on a ça, on peut démarrer. On va créer une div avec la class red_round avec juste en-dessous, un button avec la class my_button et l’attribut data-color

<div class="round red_round"></div>
<button class="my_button" data-color="red">Bouton rouge</button>

On ajoute du style classique dans un fichier css

On passe au Javascript (j’utilise JQuery personnellement pour aller plus vite, je sais les perfs, tout ça…)

<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script>
    $(document).ready(function() {
        $('.round').hide();
        $('.my_button').on('click', function() {
            var color = $(this).attr('data-color');
            $('.'+color+'_round').show();
        });    
    });
</script>

Voilà, on a un beau code maintenant, voici ce que ça donne :

Contenu du home.ejs

<!DOCTYPE HTML>
<html lang="fr">
    <head>          
        <title>Remote Control</title>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="css/styles.css">
    </head>
    <body>          
        <div class="round red_round"></div>
        <button class="my_button" data-color="red">Bouton rouge</button>
        <script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
        <script src="js/main.js"></script>
     </body>
</html>

Contenu du styles.css

.round {
    width: 100px;
    height: 100px;
}       
.red_round {
    background-color: red;
}

Contenu du main.js

$(document).ready(function() {

    $('.round').hide();

    $('.my_button').on('click', function() {
        var color = $(this).attr('data-color');
        $('.'+color+'_round').show();
    });
});

Etant donné qu’on a monté le serveur avec Node.js, pour accéder à la page il va falloir faire tourner Node.js (oui c’est embêtant, mais pour la suite ça ca se révéler très utile)

On va tapper un node app dans la console pour démarrer le serveur.

En allant sur l’url localhost:1818, on aperçoit un beau petit “Cannot GET/”

La raison est très simple, nous n’avons défini nulle part où était notre fichier html (le fichier home.ejs est tout seul)

D’ailleurs pour utiliser EJS, le package de templating, il faudrait l’installer

npm install ejs 

Pour ceux qui l’ignorent, EJS permet de passer des variables Javascript du côté serveur vers le côté client. Ainsi avec la structure du célèbre undescore.js, on peut récupérer et afficher les variables quasi-exactement comme le PHP, avec la structure : “<% code javascript %>”

Ensuite, il faudrait l’inclure dans notre serveur puis définir que la page d’accueil est cette page home.ejs dans le dossier template

On stoppe le serveur dans la console avec un Ctrl+C, puis on le redémarre avec node app.js

Et là, miracle ! On retrouve notre page ! Du coup on peut tester notre code. En cliquant sur le bouton, le carré rouge s’affiche, super non !?

Bon, pas vraiment. Maintenant qu’on a un serveur qui tourne, un template qui s’affiche, et un bouton qui gère l’appariation d’un carré, il va falloir passer à la vitesse supérieuse.

Que socket.io soit !

Socket.io et le temps réel

socket.io est une des choses qui a rendu Node.js aussi célèbre. Il s’agit d’une technologie qui en gros, facilite le temps réel. C’est à dire que si deux personnes sont connectés sur un même site, et que l’un fait une action, l’autre pourra voir le résultat de cette action sans même avoir touché quoique ce soit ni recharger la page. C’est magique !

Les codes permettant l’utilisation des websockets (la technologie sur laquelle se base socket.io) avec ce package sont très simples.

npm install socket.io
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
    // Ecoute des sockets ici
});

En rajoutant ça à la fin de notre app.js, on a notre écoute du serveur avec socket.io. Simple non ?

socket.on('buttonColor', function (color) {
    socket.broadcast.emit('showColor', color);
});

On est prêt à recevoir la fonction avec pour nom d’envoi “buttonColor” pour renvoyer ensuite la un socket “showColor”

On va inclure socket.io dans le template EJS maintenant

<script src="/socket.io/socket.io.js"></script>

Puis on l’importe dans le javascript de main.js

var app_url = 'http://localhost:1818';
var socket = io.connect(app_url);

Maintenant il ne reste plus qu’à faire des appels à ce même socket dans le Javascript, par exemple au clic sur le bouton. On supprime le show() et on le remplace par :

socket.emit('buttonColor', {color: color});

Ensuite toujours dans le code Javascript, on écrit :

socket.on('showColor', function(color) {
    $('.'+color.color+'_round').show();
});

On refait un Ctrl+C puis un node app.js

Et là que se passe t-il ? On ne voit rien en cliquant sur le bouton.

C’est normal ! Ouvrez la même URL sur un autre navigateur (Mozilla, Chrome…)

Mettez les deux à côtés, et cliquer sur le bouton.

Magie, dans l’autre navigateur, le carré rouge s’est affiché ! Vous venez d’utiliser votre premier websocket.

Et voilà, on a fait du temps réel ! :)

Pour aller un poil plus loin, nous allons créer d’autres boutons et d’autres carrés de couleur (toujours associés aux boutons)

On peut également faire disparaitre les carrés après leur affichage, voilà ce que donnerais le HTML :

<div class="round red_round"></div>
<div class="round blue_round"></div>
<div class="round purple_round"></div>

<button class="my_button" data-color="red">Bouton rouge</button>
<button class="my_button" data-color="blue">Bouton bleu</button>
<button class="my_button" data-color="blue">Bouton violet</button>

Le Javascript maintenant (pas très compliqué). A la suite du .show() dans la réception du socket, on rajoute :

setTimeout(function() {
    $('.'+color.color+'_round').hide();
}, 200);

Et voilà, en cliquant sur un bouton, c’est bien le carré à la couleur associée qui va apparaitre sur l’autre navigateur !

Alors bon par contre, on est pas encore arrivés au bout. Il est où le “Remote Control” avec le smartphone qui fait super classe ??

Eh bien au final c’est tout simple. Il suffit de mettre une petite condition de taille !

Attention, étant donné que vous êtes en local, vous n’allez pas pouvoir utiliser votre smartphone. Il faudra mettre cette application sur votre serveur en ligne pour essayer. Mais pas de panique, on peut remplaçer ça facilement pour montrer que ça marche bien ;)

$('.round').hide();

if($(window).width() < 600) {

    $('.my_button').on('click', function() {
        var color = $(this).attr('data-color');
        socket.emit('buttonColor', {color: color});    
    });

} else {

    $('.my_button').hide();

    socket.on('showColor', function(color) {

        $('.'+color.color+'_round').show();

        setTimeout(function() {
            $('.'+color.color+'_round').hide();
        }, 200);
    });
}

Et voilà le code complet, et tout roule ;) On obtient seulement accès aux boutons en étant sur un écran de petite taille (vous pouvez redimensionner votre navigateur pour simuler un petit écran) et les carrés de couleur apparaissent bien sur l’autre navigateur ! Si vous mettez ça en ligne sur votre serveur, vous pourrez “piloter” à distance votre site depuis votre smartphone.

Evidemment, les exemples de boutons et de carrés de couleurs sont un premier pas, concrètement cela n’a aucune utilité. Mais après quelques réflexions, je suis sûr que vous trouverez quoi faire de ces possibilités, comme piloter un jeu sur pc avec le smartphone comme manette, tout ça ;)

De mon côté, j’ai utiliser ça pour m’amuser à envoyer des roquettes par smartphone et à faire apparaitre les feux d’artifices qui en découlent sur PC, vous pouvez faire les tests sur RocketLauncher ;)