L'arborescence des répertoires

Le répertoire top est nommé radiok. Ce nom qui peut être modifié est gardé dans la variable d'environnement RADIOK_HOME avec le chemin qui mène à ce répertoire. Par exemple :
export RADIOK_HOME=/home/jplf/git/radiok

arborescence.

  • Le répertoire lib contient les fichiers audio utilisés comme feed back à certaines commandes.
  • Le répertoire vox contient de code d'analyse des commandes vocales. La première version basée sur le traitement local est dans le sous-répertoire ps. La nouvelle version utilisant le service google est dans le sous-répertoire fr.
  • Le répertoire bin contient tous les scripts bash qui encapsulent les commandes gérant mplayer et l'application web.
  • Le répertoire run stockent les fichiers générés par l'application : log files, pid, paramètres …
  • Le répertoire www/doc contient ces pages html avec les fichiers de style dans css.
  • Le répertoire www/kontrol est séparé en 2 sous-répertoires pour les parties cliente et serveur de l'application web.

Les scripts bash

Au coeur du système il y a donc mplayer qui diffuse les flux radio sélectionnés mais pour simplifier un peu son utilisation un paquet de scripts a été développé. Ces scripts stockent des variables d'environnement, des paramètres de configuration, etc. Ils peuvent être utilisés tels quels pour contrôler la radio pourvu qu'on soit connecté sur la raspberry. Néanmoins ils ont d'abord été conçus pour être interfacés avec le serveur http.

onair.sh

C'est le principal script de l'application. Il encapsule l'appel à mplayer(1). Il accepte les options suivantes:
  • -h affiche les options possibles et la liste des identifiants de stations de radio.
  • -s affiche le statut actuel du programme, c'est-à-dire l'identifiant de la station et le pid du process mplayer.
  • -k tue un process mplayer qui tournerait. Cette option lance le script offair.sh.
  • -l donne la liste des stations de radio gérées par l'application. La liste est une suite de couples (clé, nom). La clé sert d'identifiant court, le nom est plus explicite et peut être affiché sur une page web.
  • -t permet de définir une durée pour l'écoute de la radio. La durée expirée mplayer s'arrête. Le temps doit être donné en minutes.
Le dernier argument doit être l'identifiant de la radio.

À l'origine ce script devait être simple. Il a grossi pour tenter de répondre à des besoins de plus en plus nombreux mais il aurait sans doute été plus judicieux de choisir un autre langage pour son écriture. Une future version pourrait être écrite en python par exemple.

offair.sh

Ce script tue les process mplayer qui tournent et met à jour les fichiers qui doivent l'être.

atrmall.sh

Ce script de nettoyage supprime tous les jobs postés par at(1) mais non encore exécutés.

get_volume.sh

Ce script permet de récupérer la valeur courante du volume son. Il appelle amixer(1) et extrait le nombre en pourcentage.

set_volume.sh

Ce script change la valeur du volume son. Il appelle amixer(1) avec la nouvelle valeur en pourcentage ou avec un increment ou un decrement en dB. La nouvelle valeur du volume est sauvegardée dans le fichier run/volume

get_state.sh

Ce script génère un fichier json contenant un certain nombre de paramètres décrivant l'état de l'application.

say.sh

Ce script encapsule aplay(1) et génère un son avec un fichier de feedback stocké dans lib/sounds. Contrairement à tell.sh les fichiers son doivent être enregistrés à l'avance.

tell.sh

Ce script encapsule l'utilisation de l'outil de synthèse vocale mis en ligne par google. Il permet de fournir un feed back et peut servir d'alternative à say.sh car il est capable de générer du français correct à partir d'une courte chaine de caractères.

listen.sh

Ce script encapsule le programme de contrôle vocal whatusay avec les options qui vont bien. Le programme est lancé via screen(1) ce qui permet de récupérer en cas de besoin les messages envoyés sur la sortie standard même si le terminal d'où est lancé le script a disparu.

start.sh

Ce script démarre le serveur web permettant de contrôler l'application à distance. Là aussi la commande screen(1) est utilisée pour récupérer le terminal dans la plupart des situations.

radiok.sh

Ce dernier script démarre tout ce qui est nécessaire. Il est conçu pour être appelé dans un cron(1) au reboot de la raspberry avec la requête @reboot. Comme la rpi n'a pas d'horloge sauvegardant le temps il est nécessaire d'attendre un moment pour démarrer le serveur web, sinon l'application prendra comme référence des temps le 1er janvier 1970 ce qui est source de mauvaise surprise. En attendant quelques minutes le démon ntp a le temps de mettre à jour l'horloge avec la valeur fournie par les serveurs de temps trouvés sur l'internet.

Le serveur http

Pour intéragir aisément avec le système une solution basée sur le protocole http est toute indiquée. Une fois implémentée on peut utiliser simplement un navigateur internet pour démarrer, arrêter la radio, choisir une station, mettre en service l'alarme. Il n'est plus nécessaire de se connecter à la raspberry par ssh, on peut effectuer les opérations depuis n'importe quel ordinateur relié au réseau.

Pour réaliser ce server web et l'installer sur la raspberry la technologie NodeJs a été choisie. Il y a maintenant un nombre très important de bibliothèques et de modules utilitaires pour cet environnement. La programmation se fait en javascript ce qui permet d'avoir des résultats très rapidement.

Le choix de cette technologie a été motivé par plusieurs raisons : c'est une technlogie qui a le vent en poupe, qui dispose de bibliothèques très riches, qui s'interface très facilement avec toute sorte d'environnement et qui est très performante. En revanche beaucoup d'outils sont très pauvrement documentés et il est nécessaire de faire parfois pas mal d'essai pour comprendre comment les utiliser correctement.

Naturellememt d'autres choix auraient été possibles pour implémenter le serveur de contrôle : apache et php, tomcat et jsp, etc.

Le code se trouve dans le répertoire www/kontrol. Ce qui fait un peu fonction de programme main est dans le fichier app.js. Pour démarrer le serveur il suffit de lancer : node app.js. En fait pour avoir les bons chemins de fichier il est préférable d'utiliser le script bash start.sh qui vérifie les variables d'environnement avant de lancer node. L'application web est gérée par le framework express. Ce module fournit toutes les fonctions nécessaires à l'implémentation d'une webapp. Malheureusement la documentation en est particulièrement nulle mais avec de la patience on arrive à faire ce qu'on veut.
Dans le sous-répertoire server on trouve les deux fichiers qui contiennent les procédures traitant les requêtes arrivant au serveur.

box.js

Ce fichier contient le code qui traite les requêtes envoyées depuis un navigateur. Chaque requête se présente sous la forme /box/command/:parameter.
Pour chaque commande (start, get_volume, …) une fonction callback est définie. Cette fonction effectue le traitement, généralement le lancement d'un script bash, puis renvoie au client une réponse qui est le résultat du traitement.

La procédure la plus complexe concerne la gestion de l'alarme. Le but est de déclencher à un moment déterminé la radio. Pour utiliser l'application comme réveil-matin il suffit de mettre en route mplayer tous les matins à une heure fixée. Ceci a d'abord été réalisé grâce à un modulenode-cron mais qui n'a plus fonctionné après une mise à jour de nodejs. L'implémentation actuelle manipule des fichiers unix crontab(1) et est particulièrement robuste.

vox.js

Ce deuxième fichier de code serveur contient les procédures de traitement des commandes vocales. Le programme d'analyse vocale whatusay joue un rôle de client http pour le serveur web. Il transmet les mots qu'il a compris par une requête http préparée avec les fonctions de la bibliothèque curl.

Dans vox.js la requête /vox/process/:word reçu de whatusay est traitée en fonction du paramètre word : un script est exécuté pour lancer mplayer, régler le volume du son, changer la station etc.
Pour plus de souplesse les mots du vocabulaire de commande ont été groupés en synonymes.
Compte-tenu des temps de réponses parfois un peu longs (plusieurs dizaines de secondes), dûs essentiellement au remplissage du cache de mplayer un retour est donné à l'utilisateur sous forme de messages enregistrés pour lui indiquer ce qui a été compris correctement par le serveur ou compris de travers !

Le client web

Outre les scripts bash et la commande vocale des pages web sont disponibles pour contrôler l'application. En les affichant dans un navigateur internet on peut également démarrer la radio, l'éteindre, choisir son heure de réveil, etc. en cliquant sur les boutons proposés.

Comme il se doit le code de cette interface se trouve dans le sous-répertoire www/kontrol/client.
Le style des pages html est défini dans le fichier radiok.less qu'il faut transformer avec la commande lessc pour créer la feuille de style radiok.css.

Les pages web, en fait la page web puisqu'il n'y en a qu'une, sont manipulées par la bibliothèque AngularJS qui est un framework web développé par Google. La gestion des interactions fait aussi appel à la bibliothèque jQuery.

Le code javascript spécifique à l'application est disponible dans le fichier main-module.js dans le sous-répertoire js. Ce code définit la navigation - l'affichage - entre les différents contenus : liste des stations, déclenchement de la radio, état de l'application. Il gère les variables nécessaires à l'application, envoie les requêtes au serveur http et récupère les réponses du serveur.