Un répondeur multilingue avec Asterisk

Ayant de la famille à l'étranger, je me souviens d'un incident où des membres de ma famille avaient tenté de m'appeler sur mon portable et qu'ils n'avaient pas compris qu'ils étaient tombés sur mon répondeur, probablement du fait de mon annonce en français.

C'est pourquoi j'ai toujours pensé qu'un répondeur qui sache diffuser son annonce dans la bonne langue, en la dérivant du numéro de l'appelant, serait fort appréciable.

Un tel service va généralement au-delà de ce que fournit un opérateur téléphonique. Je me suis donc dit que ce serait là un bon exercice pour mettre en place un serveur de téléphonie Asterisk. Ce faisant, cela me permettrait également de pallier d'autres lacunes de mon propre équipement ou tout simplement réaliser des applications plus ludiques plus tard.

Présentation d'Asterisk

On présente souvent Asterisk comme étant un IPBX, c'est-à-dire un autocommutateur téléphonique privé (aussi appelé PBX) qui fonctionne en voix sur IP. On trouve beaucoup d'autocommutateurs dans des entreprises ou institutions publiques : lorsqu'on appelle un numéro et qu'on entend une voix robotisée demander un numéro de poste, ou qu'on se retrouve face à un menu, c'est le PBX qui "répond".

Le volet "voix sur IP", quant à lui, signifie grosso modo qu'on peut utiliser Asterisk pour faire son Skype interne dont les communications ne passent pas par Microsoft (et probablement pas la NSA non plus mais je ne m'avancerai pas là-dessus, on sait jamais), tout en permettant les appels vers l'extérieur et l'utilisation aussi bien de téléphones analogiques (via les fameuses cartes dites "FXO/FXS", comme l'Openvox A400P) que des téléphones SIP (comme les Cisco qu'on voit à peu près partout) ou encore des logiciels comme Ekiga ou Linphone.

On peut donc utiliser Asterisk pour passer des appels externes depuis un PC muni d'un casque et d'un micro, à l'aide d'un logiciel appelé "softphone", ce qui est pratique lorsqu'on est amené à prendre beaucoup de notes pendant la conversation. Mais on peut aussi brancher directement un téléphone analogique dessus, faire sonner des softphones depuis celui-ci, ou faire sonner le téléphone analogique en composant des numéros internes.

L'architecture matérielle

Pour ce faire, nous partirons du principe qu'on dispose déjà d'un serveur et d'une carte FXO/FXS avec au moins :

  • 1 module FXS sur le port 1 (pour brancher un téléphone dessus et pouvoir le faire sonner), éventuellement plusieurs sur les ports 2 et 3 le cas échéant;
  • 1 module FXO sur le port 4, qui ira dans la prise FXS ("téléphone") de sa box ADSL ou directement dans le mur.

Enfin, nous nous munirons également d'un bon vieux téléphone analogique (c.à.d. conçus pour se brancher sur une prise en T ou sur une prise RJ11 murale et non pas sur un réseau Ethernet). Pas que ce soit forcément nécessaire, mais comme je disposais déjà d'un téléphone avant de migrer vers Asterisk, ce serait dommage de ne pas s'en servir.

Le plan de numérotation

Installer Asterisk implique déjà de réfléchir à un plan de numérotation. Même si ce n'est pas forcément obligatoire dans notre cas, cela facilitera grandement les tests. Chaque terminal susceptible de se connecter au serveur Asterisk (dans notre cas, un téléphone analogique) doit donc disposer d'un numéro.

Dans mon cas, comme la plage des numéros à 4 chiffres commençant par 4 n'est pas utilisée par France Télécom et que je souhaite que le reste des numéros composés soit redirigée vers l'extérieur (pas de 9 ou de 0 à composer avant d'obtenir une ligne externe), j'adopterai le plan suivant :

  • 4001 pour le téléphone analogique;
  • 4002 à 4099 pour d'autres téléphones, éventuellement ;
  • 4100 pour écouter ses messages vocaux ;
  • n'importe quelle autre plage de numéros valable et attribuée par l'ARCEP sera redirigée vers l'extérieur.

Ce plan donne donc le fichier extensions.conf suivant :

[trunkint]
;
; Appels téléphoniques internationaux
;
exten => _00.,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})

[trunknorm]

; Appels téléphoniques "locaux"
exten => _0[12345679]XXXXXXXX,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
exten => _3XXX,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})

; Numéros Azur (prix appel local)
exten => _081XXXXXXX,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})

[trunknumverts]

; Numéros verts
exten => _080XXXXXXX,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
exten => _10XX,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})

[trunknumsurtax]

; Numéros surtaxés
exten => _08[289]XXXXXXX,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})

; Services de renseignements à la con
exten => _118XXX,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})

[trunknumurg]
; SAMU
exten => 15,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
; Police/gendarmerie
exten => 17,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
; Pompiers
exten => 18,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
; Numéro d'urgence européen
exten => 112,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
; Personnes sourdes ou malentendantes
exten => 114,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
; Urgences sociales ("SAMU social")
exten => 115,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
; Enfants disparus
exten => 116000,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})
; Enfance maltraitée
exten => 119,1,Dial(${GLOBAL(OUT_PSTN)}/${EXTEN})

[phones]

include => internal

include => trunknorm
include => trunknumurg
include => trunknumsurtax
include => trunknumverts
include => trunkint


[internal]

exten => 4001,1,Dial(DAHDI/1,25,x)      ; téléphone analogique
  same => n,VoiceMail(${EXTEN},s)
  same => 101,VoiceMail(${EXTEN},s)

exten => 4100,1,NoOp()
  same => n,VoiceMailMain(${CALLERID(num)})

On déclare donc tout d'abord tous les numéros de téléphone pour lesquels on souhaite relayer l'appel vers l'extérieur. Il s'agit bien entendu de tous les numéros en zéro-quelque-chose à 10 chiffres, mais aussi tous les numéros courts en 4 chiffres (seuls ceux commençant par 1 et 3 sont attribués) et, très important, les numéros d'urgence.

La configuration du canal analogique

Il faut également configurer le fichier chan_dahdi.conf avec au moins les directives suivantes :

[channels]

signalling=fxo_ks
callerid="Votre nom ici" <4001>
mailbox=4001
group=0
context=phones
language=fr
channel => 1


signalling=fxs_ks
callerid=asreceived
group=1
context=incoming
busydetect=yes
busycount=3
busypattern=500,500
language=fr
channel => 4

Cette configuration est normalement en partie auto-générée, mais j'ai ajouté quelques éléments dans le bloc correspondant au "channel" 4 (i.e. le port 4, celui branché sur l'extérieur). J'ai ajouté busydetect=yes, busycount=3 et busypattern=500,500 parce que sinon, la carte ne sait pas quand l'interlocuteur a raccroché (ma Livebox ne fournit pas de signal spécifique lorsque la ligne a été libérée, en tout cas).

Enfin, pour que la suppression d'écho se fasse correctement, il faut charger le module wctdm (ou celui nécessaire pour votre carte) avec l'option opermode=TBR21 pour régler l'impédance de ligne à la valeur adaptée pour la France. Il suffit d'ajouter dans /etc/modprobe.d/dahdi.conf la ligne :

options wctdm opermode=TBR21

Redémarrer la machine, ou taper rmmod wctdm; modprobe wctdm en tant que root.

Les boîtes vocales

Avant de continuer, il faut savoir qu'Asterisk ne fournit pas automatiquement une boîte vocale par utilisateur ou numéro de téléphone, mais qu'il faut les configurer explicitement. Dans notre cas, on va simplement mettre en place une messagerie vocale pour le 4001. Il suffit d'ajouter dans voicemail.conf :

[default]
4001 => 1337,Téléphone,vous@example.com

Ceci crée une boîte vocale pour le 4001, avec comme mot de passe 1337 et comme nom d'utilisateur "Téléphone". Les e-mails seront envoyés à vous@example.com. Tant qu'on y est, modifions la variable emailbody pour que le message soit en français (oui c'est sur une seule ligne) :

emailbody=${VM_NAME},\n\n${VM_CALLERID} vous a ${IF($["${VM_CIDNUM}" =
"${ORIG_VM_CIDNUM}"]?laissé:transféré)} un message de longueur ${VM_DUR}\ndans
votre boîte vocale ${VM_MAILBOX} le ${VM_DATE}.\n${IF($["${VM_CIDNUM}" =
"${ORIG_VM_CIDNUM}"]?:Ce message a été laissé par ${ORIG_VM_CALLERID} le
${ORIG_VM_DATE}.)}\nVous pouvez l'écouter en appelant le 4100 depuis un
téléphone de l'appartement ou en téléchargeant\nla pièce jointe.\n

Les appels entrants

Cette configuration permet d'émettre des appels depuis un téléphone interne, mais pas d'en recevoir !

Comme on peut le voir, décrocher son téléphone analogique le place dans le contexte "phones" depuis lequel on peut appeler les numéros externes et internes. Cependant, un signal de sonnerie de l'extérieur place l'appelant dans le contexte "incoming", que nous n'avons pas encore paramétré.

L'idée principale étant que tout appel arrivant dans le contexte incoming sera simplement relayé vers le téléphone analogique. C'est là-dedans que nous allons faire le changement de langue.

On en profite tout d'abord pour envoyer bouler les appels masqués avec PrivacyManager, parce qu'il s'agit généralement de personnes indésirables. Cette application invite l'interlocuteur à composer son propre numéro de téléphone, qui sera ensuite affiché sur les téléphones lorsqu'ils sonnent. Une mesure temporaire, car j'envisage de remplacer cela par une invite qui demande à la personne de s'identifier oralement.

Le principe est simple : tout ce qui a "0031" comme 4 premiers caractères vient des Pays-Bas, et on change donc la langue en néerlandais ; tout ce qui commence par 0049 (Royaume-Uni) ou 001 (États-Unis/Canada) déclenche un changement de langue en anglais (y compris le Québec, mais je vous laisserai trouver les indicatifs correspondants vous-mêmes). Dans le cas contraire, on laisse en français.

On fait sonner le téléphone sur le port 1 de la carte pendant 25 secondes, puis on passe au répondeur.

[incoming] 

include => internal

exten => s,1,PrivacyManager()
  same => 2,Set(MYLANGUAGE=DEFAULT)
  same => 3,Set(MYLANGUAGE=${IF($[ ${CALLERID(num):0:4} = 0031 ] ? nl)})
  same => 4,Set(MYLANGUAGE=${IF($[ ${CALLERID(num):0:4} = 0049 ] ? en)})
  same => 5,Set(MYLANGUAGE=${IF($[ ${CALLERID(num):0:3} = 001 ] ? en)})
  same => 6,Set(MYLANGUAGE=${IF($[ ${MYLANGUAGE} = DEFAULT ]) ? fr})
  same => 7,Set(CHANNEL(language)=${MYLANGUAGE})
  same => 8(privmgr-passed),NoOp(${CHANNEL(language)})
  same => 9,Dial(DAHDI/1,25,x)
  same => 10,Playback(cust-vm-intro)
  same => 11,VoiceMail(4001,s)
  same => 12,Playback(vm-nobodyavail)
  same => 13,Hangup()
  same => 109,Playback(cust-vm-intro)
  same => 110,VoiceMail(4001,s)
  same => 111,Hangup()

Il suffit ensuite d'enregistrer deux exemplaires de l'annonce répondeur, en WAV 16 bits mono 8 kHz, et de les placer dans /usr/share/asterisk/sounds/<LANGUE>/cust-vm-intro.wav. Normalement, cela suffit. L'option s de VoiceMail() désactive l'annonce par défaut pour le répondeur et laisse uniquement le bip sonore.

Pour enregistrer ses annonces vocales, le plus simple est de mettre en place un numéro "virtuel" dans le contexte internal, qui active la boîte vocale du téléphone analogique. Il suffit d'enregistrer une annonce par ce biais et récupérer le message envoyé par e-mail :

exten => 4102,VoiceMail(4001,s)

Ainsi, en composant le 4102 depuis le téléphone, on entendra juste un bip sonore, puis à vous d'enregistrer les annonces pour votre répondeur, un par un. Une fois que vous avez récupéré les pièces jointes, composez le 4100 pour accéder à votre répondeur et supprimer les annonces que vous venez d'enregistrer.

Une fois que tout est en place, il suffit tout simplement de relancer Asterisk.

Le résultat final est qu'en cas de non-réponse, l'annonce cust-vm-intro est lue dans la bonne langue, puis l'appelant entendra un bip et pourra enregistrer son message. Si, au contraire, on tombe sur la messagerie vocale de la Livebox par exemple, il faut régler celui-ci pour que le répondeur se déclenche au bout de 9 sonneries (au lieu de 5), et s'arranger pour qu'Asterisk réponde avant.

Et en bonus, on reçoit également un exemplaire du message vocal par e-mail, en pièce jointe, ce qui est totalement la classe.

Conclusion

Tout cela paraît peut-être un peu tordu juste pour ajouter une seule fonctionnalité, mais on peut imaginer beaucoup d'autres possibilités. Le fait que le langage des plans de numérotation soit Turing-complet permet à n'importe qui de mettre en place son système téléphonique avec ses besoins spécifiques. Ce projet ne m'aura coûté que 220 euros pour la carte FXO/FXS, ce qui paraît un peu cher à première vue, mais reste tout à fait respectable pour le service que cela rend.

Il y a peut-être des choses que je pourrais améliorer dans mon plan de numérotation, mais j'ai essayé de vous montrer le strict minimum nécessaire pour utiliser une ligne téléphonique analogique avec Asterisk.

Comme ma ligne est derrière une Livebox, une idée connexe consisterait à laisser Asterisk s'enregistrer lui-même auprès du serveur de téléphonie Orange ; après tout, j'ai déjà pu voir comment ça marche. Ceci serait fort appréciable pour ceux qui souhaiteraient utiliser leur propre matériel au lieu de leur Livebox tout en conservant le téléphone.

Enfin, pour plus d'informations sur comment fonctionne Asterisk ou le téléphone, je vous conseille de lire l'excellent Asterisk™: The Future of Telephony disponible en PDF.

Posté par x0r à 2 commentaires • Tags : sip voip asterisk telephone fxo fxs

Commentaires

Poster un commentaire

#1 — dgonneau

Bonjour,

Merci pour tes super articles. Je cherche justement à monter une solution asterisk et je regarde les cartes fxo/fxs. Tu as pris quel modèle ? J'en vois qui commencent à 70€, mais tu indiques un prix de 220 € ?

Cordialement

#2 — x0r

La carte de base, qui coûte en effet aux alentours de 70 € (du moins au moment où j’ai rédigé ce billet), ne sert à rien toute seule : il faut lui adjoindre des modules pour configurer chacune des interfaces en mode FXO ou en mode FXS, selon l’usage qu’on en fait. Puisque je souhaitais utiliser une prise en mode FXO (reliée à la Livebox) et trois en mode FXS (reliées à des téléphones), il me fallait donc ajouter quatre modules, chacunes à environ 35 ou 40 € pièce. D’où le total de 220 €.

Poster un commentaire