Mise en place des services REST

Pour la mise en place des services REST deux éléments sont nécessaires :

  • le backend sous Node.js, qui sera responsable de communiquer avec l’electronique
  • le frontend sous AngularJS, responsable de l’interface graphique

Dans un premier temps, il est possible de mettre en place le projet sur son poste pour plus de facilité , avant de le pousser sur le Raspberry PI une fois le socle finalisé.

Méthode

Afin d’aller vite et en vue de la faible complexité du projet au niveau logiciel, le choix est fait de partir sur une brique fullstack générée. Pour cela on utilise AngularJS Full-Stack generator qui propose une vertical complète (MVC) : Express.js + AngularJS.

sudo apt-get install autoconf
sudo gem insall sass
sudo npm install -g yo grunt-cli bower generator-angular-fullstack
mkdir aligator
cd $_
yo angular-fullstack aligator

Cela en choisissant le minimum d’options afin de rester le plus simple possible =>  essentiellement pour ne pas avoir de base de données !

Dès lors, on peut lancer l’application à l’aide de la commande suivante :

sudo grunt build --force && sudo npm start

Et là, magie ! Nous avons une application standard opérationnel, très simple, sans authentification.

so-beautiful

Remarque : Pour ceux qui préfèrent développer en local afin de bénéficier des outils de développeurs tel que le livereload, la commande est plutôt : « grunt serve »

Après quelques personnalisations de la partie Angular voilà à quoi ça ressemble :

aligator-web-v2

Code source de l’application disponible sur github

Backend (NodeJS)

On va commencer par façonner le backend, ou autrement dit ce qui va se passer sur le Raspberry PI.

Couche « service »

On défini un service qui sera responsable de piloter les différents composants électronique :

_server/api/component/component.service.js_

Celui-ci contient :

  • la définition des composants, où le channel correspond au numéro des futures pin du GPIO qui seront utilisées :
var components = {
 led: [
   {channel: 29, name: 'Red LED', info: '#ff0000', value: 0},
   {channel: 31, name: 'Yellow LED', info: '#ffff00', value: 0},
   {channel: 32, name: 'Green LED', info: '#00ff00', value: 0},
 ],
 range: [
   {channel: [16,18], name: 'Range sensor 1', info: 'ultrasonic', value: 0},
 ],
 buzzer: [
   {channel: 36, name: 'Buzzer 1', info: 'buzzer', value: 0}
 ],
};
  • Les méthodes permettant de les utiliser (sujet à modification dans les prochains posts) :
componentList() {
 var result = [];
 result = result.concat(components.led);
 result = result.concat(components.buzzer);
 result = result.concat(components.motor);
 result = result.concat(components.range);
 return result;
}
action(componentId, action, value) {
  ...
  if (currentComponent.type === 'led') {
    // DO SOMETHING
  }
  ...
}

La gestion de chaque composant sera présenté dans son article dédié.

Couche « controller »

Ajout du controller :

server/api/component/component.controller.js

list(req, res) {
 res.json(service.componentList());
}

action(req, res) {
 res.json(service.action(req.body.id, req.body.action, req.body.value));
}

Glue

Pour le mapping des URLs avec le controller, on ajoute la définition des services REST disponibles sur les objets de type composant

server/api/component/index.js

'use strict';

var express = require('express');
var controller = require('./component.controller');

var router = express.Router();

router.get('/list', controller.list);
router.post('/action', controller.action);

module.exports = router;

Pour finir, on ajoute la route associée aux urls de type /api/component/* : _server/routes.js_

app.use('/api/component', require('./api/component'));

Le serveur se relançant automatiquement (pour la partie backoffice), l’accès à la page suivante retourne la liste des composants et leurs états au format json : http://url-raspberry:9000/api/component/list

Code disponible sur GitHub : https://github.com/achorein/aligator

Frontend (AngularJS)

Côté front-end rien de bien méchant, une simple consommation du service créé.

Service

Ajout d’un service générique d’envoi de requête HTTP : _client/components/rest/rest.service.js_

et d’un services pour les composants : _client/app/component/component.service.js_

Je ne détaillerais pas ces composants ici, car ils sont très simple, je met cependant le code source à disposition en fin d’article

Controller

Mise à niveau du controller de la page principale pour gérer nos actions : _client/app/main/main.controller.js_

$scope.infos = [];
componentSrv.list().then(function(data){
 $scope.infos = data;
}).catch(function(error){
 AlertService.error(error);
});

$scope.action = function(info, action, value) {
 componentSrv.action(info.id, action, value).then(function(data){
   info.value = data.value;
 }).catch(function(error){
   AlertService.error(error + ' => ' + JSON.stringify(info));
 });
};

Vue

Mise à niveau rapide de la vue. L’utilisation de composants personnalisés sera pour plus tard (filter/directive/…) : _client/app/main/main.html_

<ul class="list-group">
 <li class="list-group-item" ng-repeat="info in infos">
 <!-- LED -->
 <span ng-if="info.type=='led'">
 <span class="pull-right">
 <input type="checkbox" bs-switch switch-size="small" switch-on-color="success" switch-off-color="default"
 ng-model="info.value" ng-true-value="1" ng-false-value="0"
 ng-change="action(info, 'switch')"/>
 <button type="button" class="btn btn-sm" ng-class="info.value=='blink'?'btn-warning':'btn-default'"
 ng-click="action(info, 'blink')">
 <i class="fa fa-bullseye"></i> blink
 </button>
 </span>
 <span class="fa-stack fa-lg" ng-if="info.type=='led'">
 <i class="fa fa-stack-2x fa-circle"></i>
 <i class="fa fa-stack-1x fa-lightbulb-o fa-inverse" style="color: {{info.info}}"></i>
 </span>
 </span>
 </li>
</ul>

Et voilà

Tests

Il est maintenant possible de se connecter au Raspberry Pi et de modifier la valeur des composants. Bien entendu cela est bouchonné pour le moment. L’interfaçage avec le GPIO sera fait au fur à mesure avec les posts suivants.

Lancement au démarrage du Raspberry

Afin de lancer le serveur node au démarrage du Raspberry pi il est nécessaire de mettre en place un service unix. Pour cela nous passons par l’outils PM2 :

sudo npm install pm2 -g
sudo pm2 start /opt/aligator/server/index.js
sudo pm2 startup
sudo pm2 save

Code source

Pour plus de détail, le code source est disponible sur GitHub : https://github.com/achorein/aligator


Partager

comments powered by Disqus