rfid & android - wr0ng.name · page 5 iii-développement du projet 3.1application android 3.1.1...
TRANSCRIPT
RFID & Android
Projet n°37
Valentin Barbe, Louis Epron, Florent Gontharet
04/03/2013
Tuteur : Frédéric Pourraz
Page 1
Remerciements
Nous tenons à remercier :
Notre tuteur, Frédéric Pourraz, qui nous a suivi tout au long de projet, et nous a aidé notamment pour
le développement Android, ainsi que pour le matériel compatible.
Les professeurs et le personnel de l'IUT, qui nous ont permis d’y travailler en dehors des heures de
cours.
Page 2
Sommaire
I – Introduction ..………………………………………………………………………………..3
1.1 Présentation du sujet ...………………………………………………………………3
1.2 Motivations…………………………………………………………………………..3
II – Modules de travail………………………………………………………………………….4 2.1 Cahier des charges…………………………...……………………………………...4
2.2 Schéma synoptique………………………………………………………………….4
III – Développement du projet…………………………………………………………………5 3.1 Application Android……………………………………………………………………….5
3.1.1 Création d’un environnement Android de test et de développement ………………..5
3.1.2 Création du squelette de l’application Android……………………………………….6
3.1.3 Communication Wifi avec le serveur Linux depuis Android………………………...8
3.1.4 Gestion du RFID avec Android………………………………………………………10
3.2 Serveur Téléphonique……………………………………………………………………..12
3.2.1 Installation d’Asterisk sous Debian…………………………………………………..12
3.2.2 Création des utilisateurs SIP………………………………………………………….13
3.2.3 Configuration du plan de numérotation …..………………………………………....15
3.2.4 Configuration de la messagerie……………………………………………………….17
3.3 Communication serveur et script AGI…………………………………………………….18
3.3.1 Serveur et réception des identifiants………………………………………………….18
3.3.2 Base de données………………………………………………………………………19
3.3.3 Journal d’évènements ...………………………………………………………………22
3.3.4 Wake On Lan ……...…………………………………………………………………24
3.3.5 Script plan de numérotation…………………………………………………………..25
IV – Conclusion…………………………………………………………………………………26
V – Lexique……………………………………………………………………………………...27
VI – Bibliographie………………………………………………………………………………30
VII – Annexes……………………………………………………………………………………31 7.1 Annexe 1 : Installation et configuration du softphone Xlite………………………..31
7.2 Annexe 2 : Fichier sip.conf………………………………………………………….33
7.3 Annexe 3 : Fichier extensions.conf………………………………………………….34
7.4 Annexe 4 : Fichier voicemail.conf………………………………………….……….35
7.5 Annexe 5 : Android classe principale (ForegroundDispatch.java)………………….36
7.6 Annexe 6 : Android classe Affichage……………………………………………….39
7.7 Annexe 7 : AndroidManifest.xml…………………………………………………...42
7.8 Annexe 8 : Serveur.py……………………………………………………………….43
7.9 Annexe 9 : script.agi…………………………………………………………………47
7.10 Annexe 10 : index.php……………………………………………………………..48
7.11 Annexe 11 : connexion.php………………………………………………………..52
7.12 Annexe 12 : Requête connexion base de données……………………………….…53
VIII –Résumé……………………………………………………………………………………54
Page 3
I – Introduction
1.1 Présentation du sujet
Dans le cadre du projet technique de deuxième année, nous avons choisi de développer une solution
permettant de répertorier les horaires d’arrivée et de départ des employées d’une entreprise. Elle
permet aussi d’utiliser les portables des employés comme téléphones professionnels lorsqu’il se trouve
au sein de l’entreprise. Cela permet donc l’économie de postes téléphoniques fixes.
L’employé, lorsqu’il arrive à son bureau, scanne une puce radio (RFID) avec son téléphone Android
grâce à une application communicant avec un serveur. Ce dernier identifie alors l’utilisateur comme
“présent”, et active sa ligne téléphonique professionnelle sur son téléphone portable. Quand il part, il
rescanne la puce, et figure comme “absent” dans la base de données. Sa ligne téléphonique est coupée,
jusqu’à ce qu’il arrive de nouveau à son bureau. Les heures d'arrivée et de départ sont enregistrées
dans la base de données et consultables via une interface web.
Nous avons donc divisé le travail en trois parties. Valentin Barbe s’est occupé de l’installation et de
la configuration du serveur téléphonique. Louis Epron a mis en place la base de données, la
journalisation des événements, et le script permettant la communication entre le mobile et le serveur.
Florent Gontharet a développé l’application Android.
1.2 Motivations
Ce sujet nous a semblé intéressant car il met en avant divers aspects de notre formation. En effet,
nous avons dû installer et la configurer un serveur Asterisk et utiliser la programmation réseau.
Android étant un système récent et en expansion, nous voulions connaître les spécificités de la
programmation sur mobile. De plus, nous nous étions auparavant intéressés aux puces d’identification
RFID. Combiner ces technologies afin de mettre en place un système utile au quotidien représentait un
réel attrait.
De plus, le découpage du travail a pu se faire de manière à ce que chacun trouve sa place. Et les sujets
abordés nous apportaient a chacun de nouvelles connaissances.
Page 4
II – Modules de travail
2.1 Cahier des charges
Pour la réalisation de ce projet de gestion dynamique d’un poste de travail nous avons besoin de
trois composants principaux : un ordinateur de bureau, un téléphone mobile, et une machine faisant
office de serveur téléphonique et de serveur de base de données.
L’utilisateur devra scanner une puce RFID (puce contenant un identifiant qui caractérise l’ordinateur
où elle se trouve) en arrivant à son poste de travail. Son téléphone signalera par la suite au serveur sur
quel poste l’utilisateur se trouve, grâce au scan de la puce, et qui il est. Le serveur quant à lui,
réveillera l’ordinateur concerné et basculera les appels professionnels de l’utilisateur sur son mobile.
Lorsque l’utilisateur décide de partir, il scanne à nouveau la puce, action qui indiquera le départ de
l’utilisateur auprès du serveur. La ligne professionnelle est rebasculée sur sa messagerie. Les horaires
de départ et d'arrivée ainsi que le nom de l’utilisateur seront inscrits dans un journal d’évènements.
Ces journaux sont consultables grâce à une interface web.
2.2 Schéma Synoptique
Page 5
III-Développement du projet
3.1Application Android
3.1.1 Création d'un environnement Android de test et de développement
Le développement sous Android s'appuie sur la langage de programmation Java. Il nous faut donc
installer quelques outils indispensables.
Java est un langage orienté objet qui requiert sa propre machine virtuelle pour s’exécuter, ainsi que
des librairies de base. C'est le JRE (Java Runtime Environment), qui contient tout ce qui est
nécessaire.
Cependant, ce JRE n’exécute que du code préalablement compilé. Ainsi, on utilise le JDK (Java
Development Kit). Celui-ci contient aussi le JRE. On va donc l'installer. Celui-ci est disponible
gratuitement sur le site d'Oracle ( oracle.com/technetwork/java/javase/downloads/index.html ). Après
l'acceptation des licences et la sélection du système d'exploitation, le téléchargement et l'installation se
font automatiquement.
Un autre outil est nécessaire. En effet, Android n'utilise pas directement les librairies Java de base.
On a besoin de librairies spécifiques. Le SDK Android ( developer.android.com ) contient tout ce qu'il
faut.
Une fois ce dernier installé, on rajoute le répertoire ou se trouve le SDK au “Path”. C'est une
variable d’environnement qui contient l'emplacement des commandes exécutables. Pour se faire : clic
droit sur Poste de travail > Propriétés > Paramètres système avancés > Variable d’environnement.
Choisir ensuite « Path » dans les variables systèmes et cliquer sur modifier. Dans le champs “valeur de
la variable” à la fin, après un point-virgule, on ajoute le chemin du SDK Android téléchargé.
Le SDK utilise un manager pour gérer les différentes versions du système Android. Notre projet
utilisant la nouvelle technologie NFC, nous avons téléchargé la dernière version disponible : Android
4.2.2 (API 17).
Pour le développement, nous avons choisi Eclipse. En effet, nous avions déjà pu l'utiliser dans le
cadre des travaux pratiques de programmation. De plus, celui-ci est gratuit et disponible en
téléchargement ( eclipse.org ).
Un plug-in est disponible pour le développement d'applications Android, c'est l'ADT. Dans le menu
“Help”> "Install New Software”, il faut l'ajouter grâce à l'adresse : https://dl-
ssl.google.com/android/eclipse/ . Enfin, il ne reste plus qu'à indiquer à Eclipse ou se trouve le SDK
Android précédemment installé. Ceci grâce au menu “Windows”>’Preferences”>”Android”.
L'émulation d'appareils Android ne gérant pas la technologie NFC, nous avons utilisé un téléphone
pour nos tests. Grâce à l'ADT, nous pouvons consulter les journaux d'évènements en temps réel dans
Eclipse.
Notre environnement de travail est désormais prêt, nous allons passer au développement de
l'application.
Page 6
3.1.2 Création du squelette d'application Android
Dans Eclipse, nous avons créé un nouveau projet Android. Ce projet contient déjà son arborescence
de base.
On y retrouve un manifeste ou sont décrites les permissions requises sur le téléphone, les versions
d'Android compatibles, les spécifications de fonctionnement.
Un fichier XML (voir Annexe 7) permet de mettre en place la partie graphique de l'application.
Une classe par défaut est aussi créée. Elle contient différents comportement de l'application selon
son état.
.
Ce sont les principaux fichiers dont nous aurons besoin.
Page 7
Les besoins en permissions de notre application étant connus, nous allons les ajouter dans le
manifeste Android (l’intégralité du manifeste est disponible en Annexe 7) :
Voici le détail des différentes lignes qui nous intéresse ici :
ACCESS_NETWORK_STATE permet d'accéder à l'état du réseau ;
READ_PHONE_STATE permet de lire l'état des différents organes (NFC, Wifi) ;
WRITE_SETTINGS nous autorise à enregistrer des paramètres ;
ACCESS_WIFI_STATE permet d'accéder à l'état de liaison du wifi ;
CHANGE_WIFI_STATE permet notamment d'activer la liaison wifi ;
NFC permet d'accéder à l'adaptateur NFC du téléphone ;
INTERNET permet l'envoi et la réception de données sur le réseau.
Page 8
3.1.3 Communication avec le serveur Linux depuis Android
Pour communiquer avec le serveur, il nous faut tout d'abord créer un socket. C'est l'objet qui nous
permettra d'envoyer et de recevoir des données sur le réseau. Android ne permet pas qu'un socket soit
lancé dans le processus principal par souci de fluidité. Et un processus secondaire n'a lui pas le droit
d'afficher du contenu directement dans l'interface graphique utilisateur.
Ainsi, pour permettre les deux, on a créé une seconde classe instanciée par la première, afin
d'effectuer la tâche d'affichage de messages informatifs à l'utilisateur, et l'utilisation de notre socket.
Voici un aperçu de notre seconde classe (l’intégralité de la classe est disponible en Annexe 5) :
Différents import sont nécessaires au bon fonctionnement de notre classe. Le premier paragraphe
concerne la communication via socket. Tandis que le second concerne les différents tests de
connexion, les journaux d’événements, l'affichage, et la mise en place d'un processus secondaire.
En effet, notre classe hérite de la classe AsyncTask, qui permet de lancer une première tâche dans le
processus principal, ici l'affichage d'un message, d'en lancer une seconde dans un processus
secondaire, puis de revenir dans le premier processus pour informer l'utilisateur du bon déroulement
du processus secondaire. Les paramètres contenus en fin de ligne concernent les valeurs retournées par
ces 3 tâches.
Voici les 3 fonctions en question (l’intégralité de la classe est disponible en Annexe 6) :
La fonction onPreExecute() affiche un message d'information : « Connexion avec le serveur ... » .
Puis doInBackgroud() s’exécute, et enfin onPostExecute() affiche la réponse du serveur à l'utilisateur.
Ces fonctions sont héritées d'AsyncTask et surchargées.
Différents tests sont effectués afin de savoir si l'utilisateur est connecté au wifi, et si celui-ci est bien
le réseau où se situe le serveur à joindre. Une fois ces tests passés, le socket est initialisé, et la
connexion commence (l’intégralité de la classe est disponible en Annexe 6) :
Page 9
On peut voir que celui-ci n'a besoin que d'une adresse IP et d'un numéro de port. L'IP étant celle du
serveur, et le port celui destiné à recevoir et à traiter les informations. Ensuite on initialise deux classes
capables de lire et d'écrire dans ce socket. La méthode write() permet d'envoyer les données, et la
fonction readLine() récupère les informations retournées par le serveur. La variable response est alors
modifiée en conséquence, pour être affichée dans le onPostExecute() .
Notre application est désormais capable d'envoyer des données au serveur, et d'afficher la réponse
de ce dernier.
Page 10
3.1.4 Gestion du RFID avec Android
Le RFID est une technologie de communication radio, où une puce s'alimente avec les ondes pour
renvoyer son code d’identification. Le lecteur NFC de notre téléphone utilise cette technologie.
Une fois l'adaptateur NFC activé, Android va régulièrement vérifier si rien ne se trouve à portée. Si
c'est le cas, le système va sélectionner l'application cible de cette puce, pour lui faire suivre les
informations. Ce mécanisme est décrit d'une part dans le manifeste Android (l’intégralité du manifeste
est disponible en Annexe 7) :
Ici, le intent-filter indique que notre application est intéressée par les puces a portée, et qu'elle
demande au système de lui faire suivre les intent correspondant.
Dans notre classe principale, il nous faut cependant ajouter des informations (l’intégralité de la
classe est disponible en Annexe 5) :
Notre classe hérite de Activity, et de nombreux import sont présents, voici les principaux :
NfcAdapter nous permet d'accéder aux données scannées grâce à l'adaptateur NFC.
PendingIntent, Intent, IntentFilter, concernent les informations passées à l'application lorsqu'elle
est appelée. On ne va pas intercepter toutes les puces, car toutes ne nous intéressent pas. Tech.NfcV
nous donne les informations et méthodes sur un type de puce particulier.
TextView va nous permettre de modifier le texte affiché par notre application.
Quelques variables sont aussi initialisées suite à ces imports.
Lors de l'appel de notre application, on va déclarer un filtre, pour ne récupérer que les puces
de type « NfcV ». C'est le rôle de la méthode onCreate() (l’intégralité de la classe est disponible en
Annexe X) :
Ici, on récupère l'adaptateur NFC, et on déclare que l'on veut lancer l'application dès que le
téléphone scanne une puce NfcV contenant tout type d'information. Ce code est issu des exemples
disponibles avec le SDK Android.
Le comportement de l'application à sa création étant défini, nous allons passer à celui étant entraîné
par la détection d'une puce NfcV. Et c'est le travail de la méthode onNewIntent(), toujours dans notre
classe principale (l’intégralité de la classe est disponible en Annexe X) :
Page 11
Ici, lors de la réception d'un nouvel Intent, ce qui se produit lors de la lecture d'une puce par le
téléphone, on change le texte de l'application, pour donner les informations à l'utilisateur (en premier
l'identifiant de son téléphone, récupéré par la constante android.os.Build.SERIAL ).
NfcAdapter.EXTRA_ID contient l'identifiant de la puce scannée. Cependant il s'agit d'un tableau de
bytes. Un tableau de chaînes de caractères est donc défini, afin de faire correspondre à chaque byte son
caractère. Le résultat est stocké, et affiché à l'utilisateur.
De là, on instancie la classe Affichage, et on l’exécute, afin de lancer la connexion avec le serveur.
Pour la bonne gestion de l'adaptateur, on surcharge deux classes destinées à activer ou désactiver la
réception d'intent en fonction de l'état de l'application (au premier plan ou cachée). L’intégralité de la
classe est disponible en Annexe 5.
Notre application est désormais opérationnelle, à son lancement, elle reçoit le contenu d'une puce
scannée, l'envoi au serveur accompagnée de l'identifiant du téléphone. Elle affiche le résultat à
l'utilisateur, et attend la prochaine puce qui lui sera destinée.
Page 12
3.2-Serveur téléphonique
3.2.1 Installation du PABX Asterisk sous Debian
Nous avons décidé de travailler sous Debian 6. Nous avons choisi cette distribution car elle permet
une liberté dans le choix des logiciels installés, et aussi car nous avons travaillé avec tout au long de
notre DUT : c'est celle qui nous est le plus familier. De plus, le système de paquets APT est très
pratique, l'installation de logiciels se faisant très facilement. Cette distribution contient en effet plus de
29000 paquets (logiciels précompilés mis dans un format spécifique pour une installation facile sur la
machine), et la mise à jour de tous ces paquets se fait aussi très rapidement, par le biais d'une seule
commande.
Une fois Debian installé correctement sur une machine virtuelle, il a fallu installer un PABX (Private
Automatic Branch eXchange). Le choix évident était l’autocommutateur open source gratuit Asterisk.
Ce logiciel est libre et permet de transformer un ordinateur en un commutateur téléphonique privé. Il
est extrêmement complet et permet la mise en place de nombreuses fonctionnalités telles que la
messagerie, conférences vidéo, et autres. Il implémente les protocoles H320, H323 et SIP. Ce serveur
est une partie essentielle du projet, car il va permettre aux téléphones de basculer sur leur messagerie,
ou d'activer la ligne téléphonique lors du scan de la puce RFID. Il permet donc de remplacer un PABX
propriétaire très cher et d'y joindre toutes les fonctionnalités VoIP.
Pour installer Asterisk sous Debian, il suffit de taper les commandes suivantes, en s'assurant d'être
connecté en tant que « root » (commande sudo -s) :
Cette commande permet de vérifier que tous les paquets sont à jour.
Ensuite :
Celle-ci permet de lancer le téléchargement puis l'installation du serveur Asterisk.
L'installation peut prendre un certain temps.
Une fois celle-ci terminée, il faut s'assurer que le serveur sera lancé à chaque démarrage.
Pour cela, il faut aller vérifier qu'il y a un lien vers le script de lancement d'Asterisk (situé dans
/etc/init.d) dans un dossier rcX.d (X correspondant à un niveau d'exécution).
Nous pouvons voir ici que le lien est contenu dans le répertoire rc0.d.
De plus il faut aller vérifier dans le fichier /etc/default/asterisk que les deux lignes suivantes sont
présentes :
RUNASTERISK=yes
RUNASTSAFE=no
Ce sont les valeurs par défaut, mais il vaut mieux vérifier.
En lançant la commande « asterisk -vvvvc », nous pouvons voir si le serveur est installé correctement.
Asterisk est maintenant bien installé sur notre machine virtuelle. Il faut maintenant le configurer.
Page 13
3.2.2 Création des utilisateurs SIP
Pour créer des utilisateurs SIP sous Asterisk, il faut aller dans le fichier sip.conf, situé dans le
répertoire /etc/asterisk.
En l'ouvrant pour la première fois, nous trouvons beaucoup de choses déjà écrites, mais commentées
(environ 1000 lignes de code). N'influençant pas le fonctionnement du serveur, il est conseillé de ne
pas les supprimer, car des explications sur le fonctionnement du fichier de configuration y figurent.
Nous allons tout d'abord créer deux utilisateurs standards pour effectuer des tests.
Voici la démarche :
[general] est un contexte, c'est à dire que les paramètres placés ici seront appliqués à tous les
utilisateurs du contexte « general ». Ce contexte est particulier, car tous les utilisateurs en font partie.
context=default : Défini le contexte par défaut des clients SIP (en lien avec le
fichier extensions.conf)
srvlookup=yes : permet de faire des appels vers des clients dont on connaît uniquement le nom
DNS.
port=5060 : on indique ici le port SIP
disallow=all : on interdit tous les codecs, puis on va autoriser seulement ceux qui nous intéressent.
allow=gsm : on autorise le codec gsm
allow=alaw : on autorise le codec G711 loi a
allow=ulaw : on autorise le codec G711 loi µ
register => RFID:passprojet@rt-passerelle-voip : nous avons besoin pour notre projet d'un compte
SIP pouvant passer par le serveur ToIP de l'université, afin de pouvoir appeler un téléphone portable
depuis un softphone, installé sur une machine ayant accès au réseau de l'IUT.
Après avoir défini ces paramètres, il faut créer les comptes SIP.
Nous avons ici un exemple de compte, pouvant être utilisé depuis un softphone.
Voici un autre compte, qui va pouvoir appeler un téléphone portable à l’extérieur ; il doit avoir accès
au serveur ToIP de l’IUT :
Page 14
username : permet de définir le login du compte
type=friend : indique que l'utilisateur accepte les appels entrant et sortant
secret : défini le mot de passe du compte
host=dynamic : indique que le compte bénéficie d'une adresse ip dynamique
nat=no
host=rt-passerelle-voip
qualify=yes : permet de vérifier que le client est joignable. Par défaut la vérification a lieu toutes les
60 secondes.
context=default : défini le contexte du client à “default”
L’intégralité du fichier sip.conf est donnée en annexe n°2.
Ensuite, il faut recharger la configuration d'Asterisk, pour que tous les changements soient pris en
compte : dans la console Asterisk, taper la commande « reload ».Toutes les modifications ont été
appliquées au système.
Il faut ensuite vérifier que l'ajout du poste a été pris en compte :
Si tout fonctionne correctement, nous obtenons ceci :
Le nom du compte figure sur la gauche. Host correspond à l’IP de la machine sur laquelle est hébergé
le client.
Page 15
3.2.3 Configuration du plan de numérotation
Le fichier contenant le plan de numérotation est extension.conf, situé dans le répertoire /etc/asterisk.
Ce fichier est essentiel au fonctionnement d’un serveur Asterisk. C'est dans celui que l'on va indiquer
au serveur comment traiter et router les appels entrant ou sortant. C'est dans ce fichier que l'on
configure le comportement des connexions traversant notre PABX.
Dans notre fichier sip.conf, nous avons placé nos utilisateurs dans un contexte nommé «default». Nous
allons donc placer les extensions correspondantes dans ce même contexte.
Les paramètres définis dans cette section seront appliqués à toutes les extensions, étant placés dans le
contexte “general”.
Si static=yes, et writeprotect=no, celà nous permet de recharger le dialplan en utilisant la commande
“dialplan reload” dans la console Asterisk.
autofallthrough=yes : raccroche automatiquement après un appel
Voici un exemple d'extensions basiques :
Prenons la 1ère ligne. 101 est le nom d'utilisateur du client, 1 est la priorité de l'action, étant à 1 c'est
celle qui sera effectuée en premier.
Dial(SIP/101, 10, tT) permet d'appeler le 101 ; après 10 secondes de non-réponse, nous passerons
passera à l'extension suivante. tT autorise le transfert d'appel.
Enfin, Voicemail(${EXTEN}@default) enverra l'appelant sur la messagerie de l’extension passée en
paramètre (ici 101). Le fichier voicemail.conf sera présenté dans la partie suivante (page 35 ).
Pour notre projet, nous avons besoin de pouvoir joindre un téléphone portable, par le biais d’Asterisk.
Voici la façon dont nous avons procédé.
Lorsque que le compte SIP “RFID” a été créé sur le serveur ToIP de l’IUT, nous lui avons associé un
numéro de téléphone fixe, le 0450661438. Lorsque quelqu’un appelera ce numéro, il devra rediriger
l’appel sur un numéro de téléphone portable (ici 0623678866), qui correspond à celui de l’employé de
l’entreprise, qui scanne une puce RFID.
La méthode “Goto()” permet de rediriger l’extension vers une autre (ici 0623678866,1).
Donc lorsque quelqu’un appelle le 0450661438, il est redirigé sur les extensions du 0623678866.
Page 16
exten => 0623678866,2,AGI(script.agi,Barbe)
Lorsque le serveur rencontre cette extension, il va exécuter un script AGI, ayant comme paramètre le
nom d’un des clients (ici Barbe). Cela sera expliqué en détails dans une autre partie (page 25).
Le propriétaire du téléphone portable pourra donc répondre à tout appel dirigé vers le numéro du fixe.
L’intégralité du fichier extensions.conf est donnée dans l’annexe n°3.
Page 17
3.2.4 Configuration de la messagerie
La messagerie, ou boîte vocale est utilisée pour laisser un message en cas d’appel en absence. Sa
configuration se fait dans le fichier /etc/asterisk/voicemail.conf.
Nous avons ici un exemple de messagerie de l’utilisateur 101. 1234 est son mot de passe, Valentin son
prénom. [default] est le contexte de l’utilisateur.
Dans extensions.conf :
Si au bout de 5 secondes, l’utilisateur 100 ne répond pas, l’appelant sera dirigé vers sa messagerie.
Cette ligne sert à mettre en place un numéro pour que les utilisateurs puissent consulter leurs boîtes
vocales.
666 : On déclare le numéro 666 comme numéro de messagerie.
1 : Priorité
VoiceMailMain : Nous appellons l’application VoiceMailMain.
${CALLERID(num)} : Nous récupèrons le numéro de l’utilisateur qui appelle pour se connecter à sa
boîte vocale.
@default : Nous sommes dans le contexte default.
L’intégralité du fichier voicemail.conf est donnée en annexe n°4.
Page 18
3.3-Communication serveur et script AGI
Les puces RFID ainsi que le téléphone utilisé ne permettent de transférer uniquement des nombres.
Pour notre projet nous avons besoin de connaitre l’identité de la personne qui scanne la puce ainsi que
l’adresse physique de l’ordinateur pour pouvoir l’allumer. Il nous faut aussi indiquer au serveur
téléphonique si la personne est à son bureau ou non. Si il est présent, ses appels seront redirigés sur
son portable.
3.3.1 Réception des identifiants RFID
Les identifiants une fois scannés doivent tout d’abord être envoyés à une machine via le réseau en wifi
à une machine faisant office de serveur. Les informations envoyées sont deux identifiants RFID de 16
caractères, celui du téléphone et celui de la puce du pc.
Ces deux nombres sont envoyés en tant que chaines de caractères sur un socket ouvert sur le port
50000, le programme qui réceptionne ces données est écrit en python. La bibliothèque utilisée pour
créer le serveur python s’appelle SocketServer.
Choix du langage de programmation
Pour réceptionner les identifiants il nous fallait un programme faisant office de serveur et capable
d’interagir avec la base de donnée. Le Python est un langage interprété et compatible avec beaucoup
de plateformes. Largement répandu et documenté, c’est avec lui que nous écrirons le programme.
Création du serveur (voir annexe 8)
On commence notre programme par créer une instance de SocketServer.
serveur = SocketServer.TCPServer(adresse_serveur, Traitementrequete)
Et on lance le serveur :
serveur.serve_forever()
Les paramètres passés sont l’adresse que l’on veut attribuer à notre serveur et en second paramètre on
trouve une classe Traitementrequete contenant la méthode handle.
La méthode handle s’exécute à chaque fois qu’un client se connecte. C’est dans cette méthode que
nous allons récupérer les identifiants et effectuer les différents traitements voulus.
class Traitementrequete(SocketServer.StreamRequestHandler):
def handle(self): #Méthode s'exécutant à chaque client qui se connecte
#on récupère les id rfid
…
#connexion à la BDD
…
#récupération du nom correspondant à l'id_client récupérer
…
…
Récupération des identifiants
Une fois le client connecté au serveur, il envoi deux chaines de 16 caractères, c’est grâce à la fonction
recv() que nous allons réceptionner et placer les identifiants dans deux variables id_client et id_pc .
Lors de l’envoi, des caractères sont rajoutés, pour récupérer la chaine qui nous intéresse on applique
les fonctions format() et strip().
id_client = format(self.request.recv(16).strip())
id_pc = format(self.request.recv(16).strip())
Le paramètre 16 étant le nombre de caractères à recevoir.
Page 19
3.3.2 Base de données (voir annexe 12)
Maintenant que notre serveur possède les identifiants de qui arrive/part et l’identifiant de sa machine,
il faut qu’on les compare avec ceux présents dans la base de données pour trouver la correspondance
identifiant
Modèle Conceptuelle de Données :
Le champ present de la table projet_utilisateurs indique si le statut de l’utilisateur est à « présent » ou
à « absent ».
Le champ mac_pc correspond à l’adresse physique (MAC) du PC, cette adresse est utile pour le réveil
du pc.
Pour notre base de données nous avons choisi PostgreSQL, c’est un système de base de données
répandu avec une gestion du relationnelle aisée. Pour l’administration nous avons utilisé le logiciel
pgAdmin III, il nous a permis d’avoir une interface graphique convenable pour notre base de données.
Page 20
Pour résumé : projet_utilisateurs -> recense les utilisateurs et leur identifiant rfid
projet_pc ->recense les adresse physique des pc et leur identifiant rfid
projet_log->enregistre le scan de tel utilisateur sur tel pc à une tel date
bibliothèque Psycopg2 qui fournit un
ensemble de fonctions permettant notamment la connexion à notre base et l’exécution de requêtes
SQL.
Connexion à la base « projet » :
con = psycopg2.connect("dbname=projet user=louis password=louis host=127.0.0.1 port=5432")
Récupération du nom de l’utilisateur qui scan :
cur = con.cursor()
cur.execute("SELECT nom FROM projet_utilisateurs WHERE id_utilisateur='" +
id_client+"'")
nom_utilisateur = cur.fetchone()
Page 21
Idem pour l’adresse du pc :
cur2 = con.cursor()
cur2.execute("SELECT mac_pc FROM projet_pc WHERE id_pc='" + id_pc +"'")
mac_pc = cur2.fetchone()
On récupère le statut de l’utilisateur (présent ou absent)
curso=con.cursor()
curso.execute("SELECT present from projet_utilisateurs where id_utilisateur='"+ id_client+"'")
presence2 = curso.fetchone()
Nous connaissons désormais le nom de l’utilisateur, l’adresse du pc scanné et si l’utilisateur arrive au
travail ou si il part : si le champ présent = « present » => l’utilisateur s’en va
Si le champ present = « absent » => l’utilisateur arrive
Il convient ensuite de changer ce statut à « absent » s’il s’en va et à « présent » si il arrive
if (presence.count('present')):
curs2=con.cursor()
curs2.execute("UPDATE projet_utilisateurs SET present='absent' WHERE id_utilisateur='"+
id_client +"'")
con.commit()
self.request.sendall("Vous venez de vous deconnecter")
elif (presence2.count('absent')):
curs2=con.cursor()
curs2.execute("UPDATE projet_utilisateurs SET present='present' WHERE id_utilisateur='"+
id_client +"'")
con.commit()
self.request.sendall("Vous venez de vous connecter")
Page 22
3.3.3 Journal des évènements (voir annexe 10 et 11)
Le journal consiste à garder une trace de chaque arrivée et départ des employés
C’est ici que la table projet_log va être utilisée, on y enregistrer à chaque fois qu’un client scanne,
son identifiant et celui de la machine ainsi que la date.
cur3 = con.cursor()
cur3.execute('INSERT INTO projet_log (refid_pc, refid_utilisateur, annee, mois, jour, heure,
statut) VALUES
(\''+id_pc+'\',\''+id_client+'\',\''+annee+'\',\''+mois+'\',\''+jour+'\',\''+heure+'\',\''+presence+'\')')
con.commit()
Ces évènements doivent ensuite être facilement consultables par l’administrateur. Nous avons donc
mis en place un serveur web Apache ainsi qu’une interface HTML/PHP répertoriant les évènements.
L’interface se compose de deux principaux fichiers index.php et connexion.php.
connexion.php contient les informations nécessaires à la connexion à la base de données. index.php
commence par tester si des paramètres lui sont envoyés.
Si aucun paramètre n’est passé alors index.php affiche le formulaire permettant de choisir l’utilisateur
et la date des logs, ces informations sont ensuite envoyées sur cette même page
Page 23
Si des paramètres sont récupérés (utilisateurs+date en GET) la page affiche le détail des logs pour cet
utilisateur à cette date :
Exemple de requêtes SQL effectuer pour obtenir les logs :
$sql = "SELECT heure, statut, nom FROM projet_log INNER JOIN
projet_utilisateurs on id_utilisateur = refid_utilisateur
WHERE nom='".$nom."'AND annee='".$annee."'AND mois='".$mois."'AND jour='".$jour."'" ;
Page 24
3.3.4 Wake On Lan (voir annexe 8)
Le WakeOnLan est une technique qui consiste à envoyer un paquet spécial appelé « Magic Packet » à
un PC éteint pour l’allumer.
Capture de trame d’un Magic Packet :
Le paquet doit être envoyé grâce à l’adresse ip de broadcast sur un nouveau socket. Le paquet utilise
aussi l’adresse MAC de broadcast comme adresse de destination. Le packet contient également
l’adresse MAC du PC à réveiller.
Création du Magic packet :
msg = '\xff' * 6 + hw_addr * 16
Création du socket :
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
Envoi du paquet
s.sendto(msg, ('10.102.76.255', 7))
Ce code n’est exécuté seulement si le statut de l’utilisateur était à absent, sous-entendu l’utilisateur
arrive au travail.
Notre serveur a maintenant rempli son rôle, il est capable de retrouver qui s’est connecté et sur quelle
machine, de plus il allume le PC scanné lorsqu’il arrive. Il reste donc à écrire un script exécuté par
Asterisk notre serveur téléphonique pour qu’il puisse déterminer si il peut renvoyer les appels
professionnels de la personne appelée sur son mobile.
Page 25
3.3.4 Script Agi (voir annexe 9)
Ce type de script est appelé script agi, le nôtre sera rédigé en Python. Ce script doit être placé dans le
plan d’extensions d’Asterisk afin qu’il soit exécuté à chaque appel.
exten => 0614921008,1,Answer()
exten => 0614921008,2,AGI(mon_script.agi,Gontharet)
exten => 0614921008,3,Dial(SIP/RFID/${EXTEN})
exten => 0614921008,4,Voicemail(151@default)
Le nom de la personne appelée est passé en paramètre au script AGI afin qu’il puisse aller déterminer
si la personne est à son travail ou pas grâce à la base de données.
La première partie consiste donc à récupérer cet argument. Pour interagir de Python à Asterisk nous
possédons deux principaux canaux, stdin pour recevoir ce que Asterisk nous envoi et stdout pour
emmètre des commandes à Asterisk.
Récupération du Nom passé en paramètre :
env = {}
while 1:
line = sys.stdin.readline().strip()
if line == '':
break
key,data = line.split(':')
if key[:4] <> 'agi_':
print("did not work")
continue
key = key.strip()
data = data.strip()
if key <> '':
env[key] = data
nom = env["agi_arg_1"]
On recherche maintenant le statut de la personne dans la base de données :
con = pg.connect('projet', '127.0.0.1', 5432 , None, None, 'louis', 'louis')
sql = con.query('SELECT present FROM projet_utilisateurs where nom=\''+ nom+'\'')
presence = sql.getresult()
La variable « presence » est testée, si elle contient « present » notre script décroche sinon il redirige
sur la messagerie
if (presence2.count('present')):
sys.stdout.write("answer \n")
else:
sys.stdout.write("exec(Voicemail(${EXTEN}@default) \n")
Notre script est maintenant terminé, il appellera la personne sur son portable si elle a scannée en
arrivant dans l’entreprise. Si elle est partie en re-scannant la puce, elle sera marquée comme absente
dans la base de données et les personnes au sein de l’entreprise qui essaieront de l’appelé sur sa ligne
professionnelle, tomberont sur sa messagerie.
Page 26
IV – Conclusion
Avec ce projet nous avons acquis de l’expérience qui nous sera utile pour nos poursuites
d’études, mais aussi dans le monde de l’entreprise. En effet, dans notre vie professionnelle, nous
devrons trouver des solutions facilitant le travail d’employés, telle que celle présentée par notre projet.
Les périphériques mobiles Android occupent aujourd’hui une part grandissante dans notre
quotidien et dans les entreprises. Le NFC est lui aussi en pleine expansion, et facilement accessible.
Asterisk est quant à lui un serveur aujourd’hui largement adopté par ces mêmes entreprises, ainsi que
les bases de données.
Combiner ces différentes technologies pour en faire un moyen simple de gérer sa ligne professionnelle
par un employé présente donc un réel intérêt, et un confort supplémentaire pour ces derniers.
D’un point de vue technique, nous avons pu approfondir nos connaissances en configuration et
mise en place de serveur Asterisk et SQL, de programmation de scripts Python, et en développement
d’applications Java et Android.
Nous avons ainsi approfondi nos connaissances en configuration et mise en place de serveur
Asterisk et SQL, de programmation de scripts Python, et en développement d’applications Java et
Android.
Notre projet peut cependant être amélioré en proposant de garder ou non la redirection de la
ligne de l’employé lors d’une déconnexion, dans le cadre d’un déplacement notamment. Et la sécurité
de notre projet pourrait être renforcée grâce à un système d’authentification par challenge par exemple.
.
Page 27
V – Lexique
Adresse IP Identifiant d'une machine sur un réseau. L'adresse est composée de 4 octets, par exemple «
192.168.145.14 » Chaque octet est compris entre 0 et 255.
ADT (Android Development Tools) Disponible comme extension d’Eclipse, il permet d’intégrer à ce dernier les options utiles lors du
développement d’une application Android. On y retrouve la création de projet assistée, la compilation
du code, la possibilité d’afficher les logs du téléphone directement dans Eclipse.
Android Système d'exploitation open source utilisant le noyau Linux, conçu pour terminaux mobiles.
APT Advanced Packaging Tool : simplifie la mise à jour et la désinstallation de logiciels sur les systèmes
Debian, en automatisant la récupération de paquets à partir de sources (internet, CD-Rom, etc...).
Asterisk Logiciel open source pour les systèmes GNU/Linux, qui transforme un ordinateur en un commutateur
téléphonique privé, ou PABX.
Bibliothèque
Ensemble de fonctions, permet entre autres de ne pas avoir à réécrire ces fonctions
Byte Ensemble de bits utilisé ici pour le codage de caractères sur une puce RFID.
Distribution Linux Fait référence à un ensemble de logiciels présents sur un système, assemblés autour du noyau Linux.
G711 Norme de compression audio : échantillonnage : 8kHz ; bande passante : 64 kbits/s ; codage MIC
(Modulation d’impulsion Codée).
Loi a : norme utilisée principalement en Europe
Loi µ : norme utilisée aux Etats-Unis et au Japon
H320/323 Protocoles utilisés par Asterisk gérant les systèmes et équipements terminaux visiophoniques :
téléphones connectés au réseau RNIS.
Init Programme sous Linux qui lance toutes les autres tâches.
Instance
Une instance d'une classe est un objet avec un comportement correspondant à cette classe et un état
initial.
Java Langage de programmation informatique orienté objet.
JDK (Java Development Kit) Contient le JRE et les outils nécessaires à la compilation du code Java.
Page 28
JRE (Java Runtime Environment) Contient l’environnement d’exécution Java, qui permet aux applications Java de s’exécuter.
Adresse MAC
C’est un identifiant physique stocké dans une carte réseau
NFC (Near Field Communication) Technologie mobile de communication en champ proche. Elle permet à deux téléphones de
communiquer, ou à un téléphone de lire une puce RFID.
NfcV Correspond à la norme ISO 15693, pour les puces de voisinage.
Niveau d'exécution linux Run Level, est un chiffre ou une lettre utilisé par le processus init des systèmes Unix pour déterminer
quelles fonctions sont activées.
PABX (Autocommutateur Privé) Private Automatic Branch eXchange : sert à relier des postes téléphoniques d'un établissement avec le
réseau téléphonique public. Permet également un nombre élevé de fonctionnalités tels que les appels
internes, appels d'urgence, conférences, messagerie, transfert d'appels, ...
RFID Radio Identification : méthode pour mémoriser et récupérer des données à distance en utilisant des
marqueurs, "radio étiquettes". Celles-ci contiennent une antenne associée à une puce électronique,
grâce à laquelle ils peuvent répondre aux requêtes radio émises par un émetteur.
Elles contiennent un identifiant qui peut identifier des objets, personnes (passeport) ou mêmes des
animaux domestiques, dont la puce peut être implantée sous la peau.
RNIS Réseau Numérique à Intégration de Services : liaison autorisant des débits allant jusqu'à 2Mbit/s, et
une meilleure qualité qu'un modem classique.
SDK (Software Development Kit) C’est un ensemble d’outils de développement. Le SDK Android inclut un débogueur, des librairies, un
émulateur pour simuler un périphérique Android, de la documentation et des exemples de code.
SIP Session Initiation Protocol : Protocole utilisé dans les télécommunications multimédia (son, image,...)
mais aussi pour la téléphonie par internet (VoIP). Peut aussi servir à d'autres applications telles que la
messagerie instantanée, la réalité virtuelle, …
Socket C’est une interface de connexion. Cette couche logicielle permet d’ouvrir des connexions distantes
sans avoir à gérer la prise en charge réseau. Permet par exemple l’établissement d’une session de
connexion entre 2 machines.
Page 29
Softphone Type de logiciel utilisé pour faire de la téléphonie par Internet depuis un ordinateur plutôt qu'un
téléphone, au moyen d'un microphone et d'un casque ou de haut-parleurs reliés à la carte son, ou d'un
périphérique semblable à un téléphone mais se branchant sur un port USB.
XML (Extensible Markup Language) langage de balisage extensible : conçu à la base pour l’échange de données complexes. Ce langage de
programmation s’apparente au HTML.
Page 30
VI - Bibliographie
VoIP et ToIP Asterisk, la téléphonie IP d’entreprise Sébastien Déon
Ce livre est paru en 2007. Il détaille toutes les étapes de la mise en place de l’autocommutateur
Asterisk. Il s’adresse à la fois à des utilisateurs débutants et à des vétérans en la matière. Ce livre nous
a permis de mettre en place le serveur Asterisk.
http://www.asterisk.org/ Site officiel du projet Asterisk. Nous pouvons y trouver toutes les versions d’Asterisk, mais
principalement une communauté très active, avec des forums sur lesquels les utilisateurs confirmés
n’hésitent pas à répondre à toute question (http://forums.asterisk.org/).
http://www.asteriskguru.com Site comprenant de nombreux tutoriels sur la mise en place d’un serveur Asterisk. Ils peuvent être très
utiles mais certains d’entre eux devraient être mis à jour, d’anciennes versions d’Asterisk étant
utilisées. Tous les articles sont en anglais.
http://astbook.asteriskdocs.org/en/2nd_Edition/asterisk-book-html-chunk/asterisk-CHP-9-
SECT-4.html Le seul vrai exemple de script agi écrit en python donc très utile.
http://developer.android.com/ Le site officiel du développement d’applications Android. On y trouve le SDK Android, de la
documentation, et des exemples.
http://www.eclipse.org/ Site du logiciel de programmation utilisé ici : Eclipse. Très présent pour la programmation Java.
http://www.linux.com/news/software/developer/10927-a-primer-to-agi-asterisk-gateway-
interface
Une bonne introduction au fonctionnement des scripts agi, très utile pour commencer.
http://www.oracle.com/ Site officiel de l’éditeur du langage de programmation Java. Le JRE et le JDK sont disponibles en
téléchargement.
http://docs.python.org/2.7/
Documentation de python 2.7, documentation clair et bien réalisée, on peut y trouver par exemple le
détail de module tel que SocketServer ou encore Psycopg2 ainsi que quelques exemples de code.
http://python.jpvweb.com/mesrecettespython/doku.php?id=client-serveur_tcp_stream
De bons exemples d’utilisation du module SocketServer
http://www.voip-info.org/ Ce site est en quelque sorte l’encyclopédie de la VoIP. Il contient un très grand nombre d’articles
facilitant la compréhension du fonctionnement d’un serveur Asterisk. Tout est rédigé en anglais. De la
documentation sur les agi y est aussi disponible.
Page 31
VII - Annexes
Annexe 1 - Installation et configuration du softphone Xlite Xlite est un logiciel gratuit développé par Counterpath. C’est un softphone multi-plateforme
disponible sous Windows et Linux.
Nous avons décidé de l’installer sous windows XP.
Lors du premier lancement, une fenêtre nous demandant de renseigner des informations d’un compte
SIP s’ouvre :
Account name : nom du compte
User ID : login de l’utilisateur, dans sip.conf
Domain : adresse IP du serveur Asterisk
Password : mot de passe de l’utilisateur figurant dans sip.conf
Page 32
Display name : nom qui s’affichera lors d’appels
Proxy : adresse IP du serveur Asterisk
Si la configuration est correctement faite, une fenêtre s’ouvre, et nous pouvons alors ajouter des
contacts, téléphoner, etc. …
Page 33
Annexe 2 - Fichier sip.conf
[general]
context=default
srvlookup=yes
;permet les appels basés sur les noms DNS
port=5060
;port SIP
dissallow=all
allow=gsm
;autorisation du codec gsm
allow=alaw
;autorisation du codec G711 alaw
allow=ulaw
;autorisation du codec G711 ulaw
register => RFID:passprojet@rt-passerelle-voip
[100]
username=100
type=friend
secret=louis
nat=no
host=dynamic
qualify=yes
context=default
[101]
username=101
type=friend
secret=valentin
host=dyanmic
nat=no
qualify=yes
context=default
[102]
username=102
type=friend
secret=florent
host=dynamic
nat=no
qualify=yes
context=default
[RFID]
type=firend
username=RFID
fromuser=RFID
secret=passprojet
host=rt-passerelle-voip
qualify=yes
disallow=all
allow=alaw
Page 34
Annexe 3 - Fichier extensions.conf
[general]
static=yes
;save dialplan
writeprotect=no
autofallthrough=yes
;raccrocher automatiquement après un appel
[default]
exten => 101,1,Answer()
exten => 101,2,Dial(SIP/101,10,tT)
exten => 101,3,Voicemail(${EXTEN}@default)
exten => 100,1,Answer()
exten => 100,2,AGI(script.agi,Epron)
exten => 100,3,Dial(SIP/100,5,tT)
exten => 100,4,Voicemail(${EXTEN}@default)
exten => 0450661438,1,Answer()
exten => 0450661438,2,Goto(0623678866,1)
exten => 0623678866,1,Answer()
exten => 0623678866,2,AGI(script.agi,Barbe)
exten => 0623678866,3,Dial(SIP/RFID/${EXTEN})
exten => 0623678866,4,Voicemail(150@default)
exten => 0614921008,1,Answer()
exten => 0614921008,2,AGI(script.agi,Gontharet)
exten => 0614921008,3,Dial(SIP/RFID/${EXTEN})
exten => 0614921008,4,Voicemail(151@default)
;numero de la boîte vocale
exten => 666,1,VoicemailMain(${CALLERID(num)}@default)
Page 35
Annexe 4 - Fichier voicemail.conf
[general]
format=wav49|gsm|wav
attach=yes
maxsilence=10
sendvoicemail=yes
[default]
100 => 4321,louis
101 => 1234,valentin
102 => 123,florent
150 => 1234,val
151 => 12345,flo
Page 53
Annexe 12 : Requête connexion base de données :
CREATE TABLE projet_log
(
id_log serial NOT NULL,
refid_pc text NOT NULL,
refid_utilisateur text NOT NULL,
statut text NOT NULL,
mois text,
annee integer,
jour integer,
heure character varying,
CONSTRAINT projet_log_pkey PRIMARY KEY (id_log)
)
CREATE TABLE projet_pc
(
id_pc text NOT NULL,
mac_pc macaddr NOT NULL,
CONSTRAINT projet_pc_pkey PRIMARY KEY (id_pc)
)
CREATE TABLE projet_utilisateurs
(
id_utilisateur text NOT NULL,
nom text NOT NULL,
prenom text,
present text,
CONSTRAINT projet_utilisateurs_pkey PRIMARY KEY (id_utilisateur)
)
Page 54
VIII - Résumé
Nous avons réussi avec notre application Android et nos divers serveurs à utiliser le téléphone portable
de l’employé comme téléphone professionnel. Nous pouvons aussi grâce à notre système établir les
heures de présences de chaque employé tout au long de l’année. Nous pensons que sous certaines
conditions, cela peut représenter des avantages non négligeables pour une entreprise.
Thanks to this Android application and various servers, we've managed to use an employee's personnal
phone as a work phone. Thanks to our system we can also register when the employees are at work,
every day. We believe that this can bring great benefits to a company.