55
RFID & Android Projet n°37 Valentin Barbe, Louis Epron, Florent Gontharet 04/03/2013 Tuteur : Frédéric Pourraz

RFID & Android - wr0ng.name · 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

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

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 36

Annexe 5 - Android classe principale (ForegroundDispatch.java)

Page 37

Page 38

Page 39

Annexe 6 - Android classe Affichage

Page 40

Page 41

Page 42

Annexe 7 - AndroidManifest.xml

Page 43

Annexe 8 : serveur.py

Page 44

Page 45

Page 46

Page 47

Annexe 9 : script.agi

Page 48

Annexe 10 : index.php

Page 49

Page 50

Page 51

Page 52

Annexe 11 : connexion.php

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.