{"id":776,"date":"2012-09-28T01:00:00","date_gmt":"2012-09-27T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=776"},"modified":"2012-09-27T22:21:09","modified_gmt":"2012-09-27T21:21:09","slug":"asterisk-for-a-small-business-vi","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=776","title":{"rendered":"Asterisk For a Small Business (VI)"},"content":{"rendered":"<p>Last time I showed you how to add voicemail facilities to your incoming lines. We concentrated on the local end, how a single access number could pickup voicemail from different mailboxes depending on the extension it was dialled from. I didn\u00e2\u20ac\u2122t discuss the receiving side very much, and simply gave you this template:<\/p>\n<pre><code>[external]\nexten =&gt; voiptalkRESIDENTIAL,1,Verbose(1,Incoming call on callbackextension=${EXTEN})\nexten =&gt; voiptalkRESIDENTIAL,n,Queue(residential,cnrtk,,,30)\nexten =&gt; voiptalkRESIDENTIAL,n,Voicemail(household)\nexten =&gt; voiptalkOFFICE,1,Verbose(1,Incoming call on callbackextension=${EXTEN} from ${CALLERID(all)})\nexten =&gt; voiptalkOFFICE,n,Queue(business,cnrtk,,,30)\nexten =&gt; voiptalkOFFICE,n,Voicemail(business)<\/code><\/pre>\n<p>This form has an error in it. <code>Queue()<\/code> rings your extension, you answer and have a conversation, then hang up. Your caller hasn\u00e2\u20ac\u2122t hung up yet \u00e2\u20ac\u201c the <code>Queue()<\/code> call returns and they are put through to <code>Voicemail()<\/code>. That\u00e2\u20ac\u2122s unlikely to be what you want, when you hang up your extension that\u00e2\u20ac\u2122s the end of the call, and the telephone system should hang up on the caller as well. We\u00e2\u20ac\u2122ll deal with that problem, and reduce our code duplication by using a facility we have used before, subroutines.<\/p>\n<pre><code>[stdqueue]\nexten =&gt; s,1,Verbose(1,Start stdqueue ${ARG1},${ARG2},${ARG3})\nexten =&gt; s,n,Set(LOCAL(ext)=${ARG1})\nexten =&gt; s,n,Set(LOCAL(queue)=${IF($[${ISNULL(${ARG2})}]?${ext}:${ARG2})})\nexten =&gt; s,n,Set(LOCAL(mbx)=${IF($[${ISNULL(${ARG3})}]?${ext}:${ARG3})})\nexten =&gt; s,n,Queue(${queue},${QUEUEFLAGS},,,${QUEUETIMEOUT})\n; QUEUESTATUS The status of the call as a text string, one of TIMEOUT | FULL |\n;    JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL | CONTINUE\nexten =&gt; s,n,Goto(s-${QUEUESTATUS},1)\nexten =&gt; s-CONTINUE,1,Return()\nexten =&gt; s-TIMEOUT,1,Voicemail(${mbx},u)\nexten =&gt; s-TIMEOUT,n,Return()\nexten =&gt; s-FULL,1,Voicemail(${mbx},b)\nexten =&gt; s-FULL,n,Return()\n; Treat anything else as no answer\nexten =&gt; _s-.,1,Goto(s-TIMEOUT,1)<\/code><\/pre>\n<p>This is very similar to the <code>stdexten<\/code> subroutine we used in <a href=\"?p=445\">asterisk3<\/a> to standardise dialling an extension. This time the core of the subroutine is <code>Queue()<\/code> instead of <code>Dial()<\/code>, but the principle is the same. Note in particular<\/p>\n<ul>\n<li><code>Voicemail()<\/code> is only called on error conditions.<\/li>\n<li>we have passed the appropriate type flag (<code>u<\/code> or <code>b<\/code>) to <code>Voicemail()<\/code> depending on the queue fault.<\/li>\n<li>the queue to call and the fallback mailbox are parameters, but have reasonable defaults if they aren\u00e2\u20ac\u2122t present.<\/li>\n<li>the flags to the <code>Queue()<\/code> call are now a global variable, <code>${QUEUEFLAGS}<\/code>, which you should set as you wish (probably <code>cnrtkx<\/code>).<\/li>\n<li>the queue timeout is now a global variable, <code>${QUEUETIMEOUT}<\/code>.<\/li>\n<\/ul>\n<p>We can now update our <code>[external]<\/code> context to use this subroutine.<\/p>\n<pre><code>[external]\nexten =&gt; voiptalkRESIDENTIAL,1,Gosub(stdqueue,s,1(${EXTEN},residential))\nexten =&gt; voiptalkOFFICE,1,Gosub(stdqueue,s,1(${EXTEN},business))<\/code><\/pre>\n<p>We\u00e2\u20ac\u2122ve given the name of the queue to call, and <code>stdqueue<\/code> takes care of setting the mailbox to the same name when we don\u00e2\u20ac\u2122t supply an explicit mailbox.<\/p>\n<p>One extra convenience I find is to move the <code>stdqueue<\/code> calls to the internal-extensions context and then <code>Goto()<\/code> them from the external context. That means you can then easily test your queues with internal calls only. Let\u00e2\u20ac\u2122s look at the part of our dialplan that\u00e2\u20ac\u2122s doing all the mapping.<\/p>\n<pre><code>[internal-extensions]\n; Numeric aliases\nexten =&gt; 2100,1,Goto(andyp,1)\nexten =&gt; 2101,1,Goto(wife,1)\nexten =&gt; 2102,1,Goto(handytone1,1)\nexten =&gt; 2103,1,Goto(handytone2,1)\nexten =&gt; 2200,1,Goto(residential,1)\nexten =&gt; 2201,1,Goto(business,1)\n; Named extensions -- endpoints named after sip.conf sections\nexten =&gt; andyp,1,Gosub(stdexten,s,1(SIP\/${EXTEN},${EXTEN}))\nexten =&gt; andyp,hint,SIP\/${EXTEN}\nexten =&gt; wife,1,Gosub(stdexten,s,1(SIP\/${EXTEN},${EXTEN}))\nexten =&gt; wife,hint,SIP\/${EXTEN}\nexten =&gt; handytone1,1,Gosub(stdexten,s,1(SIP\/${EXTEN},${EXTEN}))\nexten =&gt; handytone1,hint,SIP\/${EXTEN}\nexten =&gt; handytone2,1,Gosub(stdexten,s,1(SIP\/${EXTEN},${EXTEN}))\nexten =&gt; handytone2,hint,SIP\/${EXTEN}\n; Named extensions -- ring groups\nexten =&gt; residential,1,Gosub(stdqueue,s,1(${EXTEN}))\nexten =&gt; business,1,Gosub(stdqueue,s,1(${EXTEN}))\n\n[internal-residential]\ninclude =&gt; internal-extensions\nexten =&gt; _0X.,1,Dial(SIP\/voiptalkRESIDENTIAL\/${EXTEN})\n\n[internal-business]\ninclude =&gt; internal-extensions\nexten =&gt; _0X.,1,Dial(SIP\/voiptalkOFFICE\/${EXTEN})\n\n[external]\nexten =&gt; voiptalkRESIDENTIAL,1,Goto(internal-residential,residential,1)\nexten =&gt; voiptalkOFFICE,1,Goto(internal-business,business,1)<\/code><\/pre>\n<p>What have we achieved then?<\/p>\n<ul>\n<li>Isolated all the call handling inside subroutines <code>stdexten<\/code> and <code>stdqueue<\/code><\/li>\n<li>Mapped the endpoints to extensions<\/li>\n<li>Supplied hints to asterisk to let it map endpoints to extensions (which we made easy by giving them the same name <code>${EXTEN}=SIP\/${EXTEN}<\/code>).<\/li>\n<li>Mapped the external lines to ring groups<\/li>\n<li>Mapped the ring groups to extensions, which can be dialled internally as well as externally<\/li>\n<li>Given everything a numeric alias<\/li>\n<li>Made dial-out use different outgoing lines depending on which extension is used (set using the <code>context=<\/code> option in <code>sip.conf<\/code>)<\/li>\n<li>Made it possible to map any endpoint onto any mailbox (set using the <code>mailbox=<\/code> option in <code>sip.conf<\/code>)<\/li>\n<\/ul>\n<p>In short: we\u00e2\u20ac\u2122re nicely organised. Adding new extensions, external lines or groups is a copy-and-paste job.<\/p>\n<p><a href=\"?p=779\">Next time<\/a> I\u00e2\u20ac\u2122ll talk about getting an Asterisk-generated dialtone.<\/p>\n<p><a href=\"?p=441\">asterisk1<\/a> <a href=\"?p=443\">asterisk2<\/a> <a href=\"?p=445\">asterisk3<\/a> <a href=\"?p=447\">asterisk4<\/a> <a href=\"?p=449\">asterisk5<\/a> <a href=\"?p=776\">asterisk6<\/a> <a href=\"?p=779\">asterisk7<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time I showed you how to add voicemail facilities to your incoming lines. We concentrated on the local end, how a single access number could pickup voicemail from different mailboxes depending on the extension it was dialled from. I didn\u00e2\u20ac\u2122t discuss the receiving side very much, and simply gave you this template: [external] exten\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=776\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[31,42,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/776"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=776"}],"version-history":[{"count":4,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/776\/revisions"}],"predecessor-version":[{"id":785,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/776\/revisions\/785"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=776"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=776"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=776"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}