- La téléphonie Internet libre basée sur Asterisk par Sylvain Thérien - http://www.tux89.com -

Recomposition sur destination occupée

L’idée de base derrière cet article est la motivation suivante. Il arrive à l’occasion que l’on tente de joindre le médecin spécialiste afin de prendre rendez-vous. Puisqu’il y a plus de demandes que d’offre, ce dernier n’offre la prise de rendez-vous qu’une fois par mois et son calendrier se complète en moins de deux heures seulement. Il n’offre pas de priorité aux urgences et l’on ne peut le joindre que par ligne directe, aucun service de répondeur ou de file d’attente. La plupart du temps, lorsque l’on réussit à joindre le bureau, son calendrier mensuel est complet et l’on doit patienter jusqu’au mois suivant.

J’ai donc effectué quelques recherches sur la recomposition automatique sur destination occupée, et les seules références dont j’ai trouvés sont les suivantes : « Asterisk tips campon [1] »

Le but est donc de réessayer la composition automatique d’un poste externe occupé à intervalle régulier en mettant l’appelant en attente avec de la musique jusqu’à ce qu’il y ait réponse au poste externe en question.

Plusieurs solutions potentielles au problème existent sur voip-info [1], dont les suivantes :

Aucune de ces solutions ne comble vraiment mes besoins. Après les avoir essayés, j’en suis venu à la conclusion qu’il existait une méthode simple d’implémenter le tout par la commande « RetryDial [2] » offerte par Asterisk.

La commande RetryDial offre les mêmes fonctionnalités que la commande Dial, mais permet en plus de recomposer automatiquement un nombre de fois déterminé avec un délai variable entre chaque essai.

En théorie, je n’aurais qu’à remplacer la commande Dial par RetryDial et le tout serait réglé, cependant j’utilise FreePBX et le contrôle du plan de composition est sous la gouverne de ce dernier. Ce qui veut dire qu’à chaque fois que j’effectue un changement via l’interface d’administration FreePBX, le fichier /etc/asterisk/extensions_additionnal.conf est régénéré automatiquement par FreePBX, et donc mes changements seraient perdus.

Je pourrais aussi remplacer une partie du plan de composition en utilisant des fichiers précis de FreePBX [3], cependant, je briserais à long terme l’évolution de FreePBX sur mon système.

Après réflexion, une solution qui me semble un compromis est de créer une nouvelle route pour ce besoin. Cela peut être fait en trois étapes simples.

Premièrement ajoutez une route spécifique pour la recomposition sur appels occupés. Disons que l’on nommera la nouvelle route « outrt-repeat-busy ». Pour inclure cette route, éditer le fichier /etc/asterisk/extensions_custom.conf et y inclure le code suivant à la fin du fichier :

; Route pour la recomposition sur appels occupés.
[outbound-allroutes-custom]
include => outrt-repeat-busy

Il est à noter que « extensions_additional.conf » fait appel à « outbound-allroutes-custom », nous permettant ainsi d’ajouter notre propre route nommée « outrt-repeat-busy ».

Deuxièmement, ajoutez le code pour cette route en copiant une route de sortie déjà existante. Dans le cas qui m’intéresse, j’ai pris la route pour les appels locaux Amérique du Nord à dix chiffres « NXXNXXXXXX » que j’ai copié à partir du fichier /etc/asterisk/extensions_additional.conf.

Éditez le fichier /etc/asterisk/extensions_custom.conf et y inclure le code suivant à la suite de modifications effectuées à l’étape précédente [outbound-allroutes-custom] :

[outrt-repeat-busy]
exten => _2NXXNXXXXXX,1,Macro(user-callerid,SKIPTTL,)
exten => _2NXXNXXXXXX,n,Set(_NODEST=)
exten => _2NXXNXXXXXX,n,Macro(record-enable,${AMPUSER},OUT,)
;exten => _2NXXNXXXXXX,n,Macro(dialout-trunk-busy,11,${EXTEN:1},,)
exten => _2NXXNXXXXXX,n,Macro(dialout-trunk-busy,10,${EXTEN:1},,)
;exten => _2NXXNXXXXXX,n,Macro(dialout-trunk-busy,8,${EXTEN:1},,)
exten => _2NXXNXXXXXX,n,Macro(outisbusy,)
; end of [outrt-repeat-busy]

Quelques explications sur le code [outrt-repeat-busy]. Cette route sera accessible en utilisant le chiffre 2 comme préfix. Si vous faites de même, assurez-vous que le chiffre 2 ne soit pas utilisé par une autre route de sortie. On doit aussi renommer l’appel à la macro « dialout-trunk » à « dialout-trunk-busy ». Il faut aussi considérer les Trunks à utiliser comme sortie. Notez que seuls les Trunks SIP, IAX et RNIS permettent d’identifier par message qu’une destination est occupée. Dans mon cas et pour la raison que je viens d’énumérer, je ne désire pas utiliser les Trunks référencés à 11 et 8, qui correspondent à ma ligne du Réseau Téléphonique Commuté  et à mon Trunk SIP vers mon cellulaire [4].  J’ai mis en commentaire les références à ces lignes en ajoutant un « ; » en début de ligne. Je n’ai gardé que le Trunk référencé à 10 qui correspond à mon fournisseur de téléphonie Internet SIP.

Afin de trouver l’index du Trunk de sortie (dans mon cas 10), exécutez la ligne de commande suivante.

egrep « OUT_..? = »  /etc/asterisk/extensions_additional.conf

Troisièmement comme dernière étape, ajoutez le code de la macro faisant appel au Trunk en copiant la macro macro-dialout-trunk qui est situé dans le fichier /etc/asterisk/extensions_additional.conf. Éditez maintenant le fichier /etc/asterisk/extensions_custom.conf et y inclure le code suivant à la suite des modifications effectuées à l’étape précédente [outrt-repeat-busy] :

[macro-dialout-trunk-busy]
exten => s,1,Set(DIAL_TRUNK=${ARG1})
exten => s,n,GosubIf($[$[« ${ARG3} » != «  »] & $[« ${DB(AMPUSER/${AMPUSER}/pinless)} » != « NOPASSWD »]]?sub-pincheck,s,1)
exten => s,n,GotoIf($[« x${OUTDISABLE_${DIAL_TRUNK}} » = « xon »]?disabletrunk,1)
exten => s,n,Set(DIAL_NUMBER=${ARG2})
exten => s,n,Set(DIAL_TRUNK_OPTIONS=${DIAL_OPTIONS})
exten => s,n,Set(OUTBOUND_GROUP=OUT_${DIAL_TRUNK})
exten => s,n,GotoIf($[« ${OUTMAXCHANS_${DIAL_TRUNK}}foo » = « foo »]?nomax)
exten => s,n,GotoIf($[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}} ]?chanfull)
exten => s,n(nomax),GotoIf($[« ${INTRACOMPANYROUTE} » = « YES »]?skipoutcid)
exten => s,n,Set(DIAL_TRUNK_OPTIONS=${TRUNK_OPTIONS})
exten => s,n,Macro(outbound-callerid,${DIAL_TRUNK})
exten => s,n(skipoutcid),ExecIf($[« ${PREFIX_TRUNK_${DIAL_TRUNK}} » != «  »],AGI,fixlocalprefix)
exten => s,n,Set(OUTNUM=${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER})
exten => s,n,Set(custom=${CUT(OUT_${DIAL_TRUNK},:,1)})
exten => s,n,ExecIf($[$[« ${MOHCLASS} » != « default »] & $[« ${MOHCLASS} » != «  »]],Set,DIAL_TRUNK_OPTIONS=M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS})
exten => s,n(gocall),Macro(dialout-trunk-predial-hook,)
exten => s,n,GotoIf($[« ${PREDIAL_HOOK_RET} » = « BYPASS »]?bypass,1)
exten => s,n,GotoIf($[« ${custom} » = « AMP »]?customtrunk)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;exten => s,n,Dial(${OUT_${DIAL_TRUNK}}/${OUTNUM},300,${DIAL_TRUNK_OPTIONS})
exten => s,n,RetryDial(,10,-1,${OUT_${DIAL_TRUNK}}/${OUTNUM},300,${DIAL_TRUNK_OPTIONS})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
exten => s,n,Goto(s-${DIALSTATUS},1)
exten => s,n(customtrunk),Set(pre_num=${CUT(OUT_${DIAL_TRUNK},$,1)})
exten => s,n,Set(the_num=${CUT(OUT_${DIAL_TRUNK},$,2)})
exten => s,n,Set(post_num=${CUT(OUT_${DIAL_TRUNK},$,3)})
exten => s,n,GotoIf($[« ${the_num} » = « OUTNUM »]?outnum:skipoutnum)
exten => s,n(outnum),Set(the_num=${OUTNUM})
exten => s,n(skipoutnum),Dial(${pre_num:4}${the_num}${post_num},300,${DIAL_TRUNK_OPTIONS})
exten => s,n,Goto(s-${DIALSTATUS},1)
exten => s,n(chanfull),Noop(max channels used up)
exten => s-BUSY,1,Noop(Dial failed due to trunk reporting BUSY – giving up)
exten => s-BUSY,n,Playtones(busy)
exten => s-BUSY,n,Busy(20)
exten => s-NOANSWER,1,Noop(Dial failed due to trunk reporting NOANSWER – giving up)
exten => s-NOANSWER,n,Playtones(congestion)
exten => s-NOANSWER,n,Congestion(20)
exten => s-CANCEL,1,Noop(Dial failed due to trunk reporting CANCEL – giving up)
exten => s-CANCEL,n,Playtones(congestion)
exten => s-CANCEL,n,Congestion(20)
exten => s-CHANUNAVAIL,1,GotoIf($[« x${OUTFAIL_${ARG1}} » = « x »]?noreport)
exten => s-CHANUNAVAIL,n,AGI(${OUTFAIL_${ARG1}})
exten => s-CHANUNAVAIL,n(noreport),Noop(TRUNK Dial failed due to ${DIALSTATUS} (hangupcause: ${HANGUPCAUSE}) – failing through to other trunks)
exten => _s-.,1,GotoIf($[« x${OUTFAIL_${ARG1}} » = « x »]?noreport)
exten => _s-.,n,AGI(${OUTFAIL_${ARG1}})
exten => _s-.,n(noreport),Noop(TRUNK Dial failed due to ${DIALSTATUS} – failing through to other trunks)
exten => disabletrunk,1,Noop(TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED – falling through to next trunk)
exten => bypass,1,Noop(TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-trunk-predial-hook)
exten => h,1,Macro(hangupcall,)
; end of [macro-dialout-trunk-busy]

Vous remarquerez que la macro a été renommée [macro-dialout-trunk-busy]. De plus, le code entre les deux lignes commentées a été adapté par rapport à la version originale du code [macro-dialout-trunk]. En fait, la ligne faisant appel à la commande Dial a été commentée et remplacée par un appel à la commande RetryDial.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;exten => s,n,Dial(${OUT_${DIAL_TRUNK}}/${OUTNUM},300,${DIAL_TRUNK_OPTIONS})
exten => s,n,RetryDial(,10,-1,${OUT_${DIAL_TRUNK}}/${OUTNUM},300,${DIAL_TRUNK_OPTIONS})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

La commande RetryDial a les particularités suivantes :

Dans le cas qui nous intéresse, j’ai spécifié les paramètres suivants :

exten => s,n,RetryDial(,10,-1,${OUT_${DIAL_TRUNK}}/${OUTNUM},300,${DIAL_TRUNK_OPTIONS})

Essai

Si vous avez deux Trunks de sorties, c’est parfait pour effectuer un test. Sinon, vous n’avez qu’à trouver un numéro pour lequel vous savez que la ligne est occupée et n’offre pas l’appel en attente.

Composez un numéro pour lequel l’on répondra, la manœuvre étant de tenir votre premier Trunk de sortie occupé. Composez maintenant le numéro correspondant à votre premier Trunk. En supposant que vous n’avez pas de fonction d’appel en attente et que votre Trunk ne supporte qu’un appel (canal) à la fois, vous devriez obtenir une tonalité occupée. Nous voici maintenant avec les conditions de base pour effectuer le test. Raccrochez votre deuxième appel et recomposez maintenant le numéro correspondant à votre premier Trunk, mais cette fois en ajoutant le préfixe identifié précédemment dans la route [outrt-repeat-busy]. Dans mon cas, le préfixe est 2. Cette fois-ci, on n’obtiendra pas une tonalité occupée, mais plutôt de la musique d’attente. Cette musique s’interrompra pour une courte durée toutes les dix secondes, signifiant que la commande RetryDial fait un autre essai de recomposition. Ce petit manège se répétera jusqu’à ce que la ligne de destination se libère ou que vous décidiez de mettre fin à l’appel.

Cette nouvelle fonction a passé haut la main la certification ISO-CONJOINTE, ce qui n’est pas peu dire :-).

Bon rendez-vous !

Références :

http://www.voip-info.org/wiki/view/Asterisk+cmd+RetryDial [2] http://www.voip-info.org/wiki/view/Asterisk+cmd+Dial [5] http://www.voip-info.org/wiki/view/Asterisk+tips+campon [1] http://www.freepbx.org/configuration_files [3] http://en.wikipedia.org/wiki/Called-party_camp-on [6] pixelstats trackingpixel
Comments Disabled (Open | Close)

Comments Disabled To "Recomposition sur destination occupée"

#1 Comment By Moustapha BA On 31 mai 2016 @ 4 h 46 min

Je vous remercie pour ce site riche d’enseignements