Avatar of Ti360
Ti360
 asked on

Asterisk Dialplan / POTS local area.

Hi experts!

New in asterisk dial plan, i'm looking the best way to manage local dial in betweens POTS and Voip.ms. I'm using 450-222 and i can have 1000 lines of local exchange to insert in my dial plan.  Ok, 122 lines compressed into pattern.  

But any way, my goal should be to use our POTS first for local call and if all POTS busy use our Voip.ms accounts.

I do not plan to create local exchange for Voip.ms as i do not think it change the rates.  

Any advice will be welcome
Voice Over IPIP Telephony

Avatar of undefined
Last Comment
tigermatt

8/22/2022 - Mon
Phonebuff

I would suggest that you use this site to get a better set of rules for your server.  Then depending on your version of FreePBX or if you are building by hand you an paste or load the results into your db, and then handle any exceptions (not usually any) that you run into.  An then enter your long distance rules as needed.

http://cohutta.com/npanxx.php

Sorry, for the second part, just place the PSTN Trunk group capital Gn first, and the VoipMS as the second group..
tigermatt

As I understand, you have two providers, and you want to ensure that calls to local numbers are routed out via one provider than the other. It just so happens that those providers use different technologies (PSTN and SIP), but as long as they are presented to Asterisk as usual, that isn't a problem.

So, there are two issues to contend with here. The first is how to dial one trunk unless it is busy, and then pass the calls out through the other. The second is how do you get calls to match just the local numbers in the first instance.

Let's tackle them one at a time.

Dialling one trunk, then the other if that is busy, is actually fairly easy. In extensions.conf, I would write (using pseudocode for the PSTN / SIP trunk names):
exten => 123,1,Dial(PSTN/123)
exten => 123,2,Dial(SIP/trunk/123)

Open in new window

You can read more about the Dial application here: http://www.voip-info.org/wiki/view/Asterisk+cmd+Dial

The important part to consider is that if a call is answered in response to a call to Dial, the Dial command will not, by default, return to continue dialplan execution. The only times it might return are if there are modifiers passed as options which override this behaviour and force it to return.

For you, that means: if the priority 1 dial statement (to PSTN) moves to state ANSWERED, when the call terminates, the second priority Dial statement (to SIP/trunk) as well as any other subsequent instructions in this extension will not be executed. So the number won't be dialled again out of the second trunk if the first trunk answered.

Now, if the first trunk (in this case, your PSTN line) was busy and replied to tell Asterisk it was busy, then Dial will return to the dialplan to continue execution. In this case, that means it would get to the priority 2 Dial statement, which will try calling 123 out the SIP trunk.

So you can do the failover bit just by stacking Dial statements together in the dialplan, as demonstrated.

The second part is going to require a bit of pattern matching in the dialplan. This means we match any extension according to a certain pattern, rather than having to key in 10000 possible local area extensions in the 450-222-XXXX range.

In extensions.conf, it is permitted to prefix an extension with the underscore (_) character. This activates pattern matching, and allows you to use a couple special pieces of syntax to achieve that. The most important ones for you will be the character class [ ... ] in which you can put individual characters or numbers to match, or a range. So _[1-3] would match the single digit 1, 2 or 3, whereas _[146] would match a 1, 4 or 6. There is also a couple of other pre-programmed character ranges - the special character 'X' is shorthand for the digits [0-9]. 'N' matches the digits [2-9], and is commonly used to match US / NANP numbers when dialled in full, as they conform to the specification NXX NXX XXXX. Outside of the US (like me), the 'N' tends to have less usage -- but that just shows Asterisk was made in the US!

On most phone systems, any attempt to access an outside line is typically prefixed with a digit, often but not always the digit '9'. This carries over from the days of key systems in which pressing '9' on a handset physically searched for an available trunk (be that a POTS trunk or a channel on a T1). When it found one, it would connect the handset directly to the outside line, and the person dialling would hear a dialtone produced by the local telco. From there, they dial directly into the line in the same way they would on a POTS telephone, and their call would be connected.

You don't have to do this with Asterisk because Asterisk will normally see the whole number before doing anything with it. (You can mimic the old format in which Asterisk connects to an outside line and then you dial the public number, but that's not a normal method of operation). Using the prefix method makes things a heck of a lot easier and means you don't have to wait for timeouts while Asterisk or a physical handset waits, to see if you're dialling more digits or not. Every access to the dialplan is deterministic. So, to match local extensions, I would search for any digit '9' followed by the 4 digits which come after the 450-222 (assuming I've understood your requirements correctly). That would be encoded as follows:

exten => _9XXXX,1,Dial(PSTN/${EXTEN:1})
exten => _9XXXX,2,Dial(SIP/trunk/450222${EXTEN:1})

Open in new window

again, where you need to replace "PSTN" with however you send calls to the PSTN, and SIP/trunk with however you send calls to your VoIP SIP trunks. The ${EXTEN:1} is a special dialplan variable which refers back to the extension which was matched - the :1 strips off the first digit, in this case, the '9'. So if I dial 94022, then the phone system would send 4022 down the POTS line. Notice in the SIP/trunk Dial statement that I prefixed the call to ${EXTEN:1} with the full area code. I'm a bit rusty on how dialling is handled in the US, but in general, you can prefix those numbers in to the Dial statement as shown and then use ${EXTEN:1} to append the last 4 digits. I assume your SIP provider would need them, but your POTS provider does not.

Your other Dial statements for long distance would just match all possible extensions in the usual way - using _9NXXNXXXXXX where you use a '9' to signify dialling an outside line. I guess in the US this could also be done with a '1' to signify the +1. Here in the UK, it was traditionally a '9'.

I may have misunderstood your question massively, but I hope this helps you make some progress.

-Matt
Ti360

ASKER
Hello Matt,  

Wow..   nice explaination, i'm new in dialplan with 60h of course. I earn basic, but i'm looking for a kind of best practice..    I'm sure that will help many people.

here is a bit of my dial plan, to keep my extensions.conf clean,i create a config file 450222local.conf and put all local exchange with pattern matching that reduce from 1000 to 121 lines.  My pattern looks like this;

[450222local]
exten => _9450214XXXX,1,Macro(localarea,${EXTEN})  

In my extensions.conf, here it's look like ( with output suppress )

[global]
#include 450222local.conf

[local]
include => 450222local
;--- test du main menu depuis l'interne
exten => **,1,Goto(mainmenu,s,1)
 same => n,Hangup()
;
;----- Internal routing
exten => _[2-5]0[1-3],1,Macro(dialexten,${EXTEN})
 same => n,Hangup()
;
exten => _[1-3],1,Macro(dialexten,${EXTEN})
 same => n,Hangup()
;
exten => 0,1,Macro(dialall,${EXTEN})
 same => n,Hangup()
;
;-----Gestionde la boite vocale
exten => *98,1,Wait(1)
 same => n,Macro(voicemailmain)
 same => n,Hangup()

[macro-localarea]
exten =>  s,1,Set(CALLERID(name)=CallerID) 
 same => n,Set(CALLERID(number)=450222XXXX)
; same => n,Dial(SIP/${EXTEN:1}@bell,60,r)
 same => n,Dial(iax2/voipms/${EXTEN:1},30,r)
 same => n,Hangup()

Open in new window

I know for testing my bell is in comment and won't be use at the moment.. Now, when i dial for example 9514774...., it sounds busy  right away..  without ringing  Here is a trace in Asterisk CLI..
    -- Executing [9514774....@local:1] Macro("SIP/301-000000b", "localarea,9514774....") in new stack 
    -- Executing [s@macro-localarea:1] Set("SIP/301-0000000b", "CALLERID(name)=CallerID") in new stack 
    -- Executing [s@macro-localarea:2] Set("SIP/301-0000000b", "CALLERID(number)=450222XXXX") in new stack
    -- Executing [s@macro-localarea:3] Dial("SIP/301-0000000b", "iax2/voipms/,30,r") in new stack 
    -- Called iax2/voipms/
    -- Hungup 'IAX2/voipms-3906'
  == Everyone is busy/congested at this time (1:0/0/1)
    -- Executing [s@macro-localarea:4] Hangup("SIP/301-0000000b", "") in new stack
  == Spawn extension (macro-localarea, s, 4) exited non-zero on 'SIP/301-0000000b' in macro 'localarea'
  == Spawn extension (local, 9514774...., 1) exited non-zero on 'SIP/301-0000000b'

Open in new window

~ Comment edited by tigermatt to obfuscate the phone number for privacy reasons ~
~ I also took the liberty of moving code blocks into [ code ] tags, just for neatness! :-) ~
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
ASKER CERTIFIED SOLUTION
tigermatt

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Ti360

ASKER
Great explication, for me and for person without lot of experience.

Thanks!
Ti360

ASKER
Matt,  

it's working great..  and of course i try it without :1 and the S was pass as the number to dial.
I'll do the same kind of marco (may be go sub ) with toll free, both provider, For long distance, i'm going to pass directly to Voip.ms..  

What's your sugestion; ( not all the solution..  i need to search a bit to learn! )

For toll free....  Sounds that we have some here in north america..  Kind of pattern matching and redirect to my macro-Localarea?
"... They include the area code 800 since 1967, 888 (since 1996), 877 (since 1998), 866 (since 2000) and 855 (since 2010). Area codes reserved for future expansion include 844, 833, 822, 880 through 887, and 889..."

For Long distance, i'm looking the same way, but need something that handle everything that doesn't match any "include file", to add 1 if needed and use voip.ms.

Thanks for your help!!!
tigermatt

I don't remember precisely how extensions are matched in Asterisk, but I think there is some priority ordering given to the order in which they are defined (although that may not be the case - I'd have to check) and of course, how 'specific' the match is.

So, I would just define your local extensions in whatever context you wish to do that first, and then define another "general" rule which acts as a catch-all for all others - e.g.:

exten => _9NXXNXXXXXX which matches '9' followed by [2-9] then any two digits, [2-9] then completes any further digits. You could also simplify this and match 'anything' using exten => _9XXX! where the ! just matches as soon as possible. Also, you can use the '.', which will wait for input (the difference is probably not a concern unless you're using phones which send every digit to Asterisk - e.g. directly attached to an FXS port in the Asterisk server, for SIP you'll be left asking what the difference is so it doesn't matter all that much).

You'll probably want to check 'premium rate' numbers cannot be dialled, and may want to look into barring those with your telephone provider. This is just a sensible security precaution in the event the box were to get compromised. A firewall in front of an Asterisk box is also a very good idea, and don't expose the SIP ports to the Internet unless you really have to!

Glad to be of assistance, I'm glad it all worked out :-)

-Matt
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.