How to Use MySipSwitch

Support zone

Ruby Dial Plan

Postby emoci » Mon Jul 14, 2008 12:06 am

1. Ruby Dial Plan Example

To put this dial plan example into context, I have the following providers:

Provider1: Outgoing Calls only, mostly North America
Provider2: Outgoing Calls only, mostly International
Provider3: Incoming DID calls (Contact field for registration set as sip:provider3.mssusername@sip.mysipswitch.com)
Provider4: Incoming DID calls (Contact field for registration set as sip:provider4.mssusername@sip.mysipswitch.com)
Provider 5: Incoming DID calls (Contact field for registration set as sip:provider5.mssusername@sip.mysipswitch.com)
SipBroker: Set up as a provider with anon username and no password
PhoneGnome: For calls to PG users
VoXalot: Default provider


The entire following Ruby script is what I am using, however I have divided in in parts to make it easier to understand how to accomplish each part.

Note that except #Ruby, everything else after a # is a comment and does not affect the program but simply is there for guidance

The whole script is one large If-else statement with more if and case statements embedded.

By dividing it into parts, it also helps for you to see a scaffold. For example, if you do not require the "#****Route Calls based on Caller ID Only****" section, simply do not use it, as long as you remember to remove the end statement corresponding to the case statement in that section:


Code: Select all
#Ruby
sys.log("***Starting New Call Event***")


#********Incoming Calls********

Code: Select all
#****This Part collects call information for the log****

if sys.In then
   sys.log("***Incoming Call Starting***")
   sys.log("Incoming Call From  #{req.Header.From.FromName} at #{req.Header.From.FromURI.User}@#{req.Header.From.FromURI.Host}")
   sys.log("Call is for #{req.URI.User}")
   cid = req.Header.From.FromURI.User
   trunk = req.URI.User
   sys.log("*** CID: #{cid} | Trunk: #{trunk} ***")



Code: Select all
#****Route Calls based on Caller ID + Trunk****

if sys.RegexMatch(trunk, "provider3.mssuser")  and sys.RegexMatch(cid, "4169391212") then
sys.log("Routing CallBack for 4169391212")
sys.Callback("14169391212@Provider1" , "*774914166239612@SipBroker" , 15)

else

if sys.RegexMatch(trunk, "provider3.mssuser")  and sys.RegexMatch(cid, "6478959191") then
sys.log("Routing CallBack for 6478959191")
sys.Callback("16478959191@Provider1" , "*774914166239612@SipBroker" , 15)


Code: Select all
else


Code: Select all
#****Route Calls based on Caller ID Only****

case cid
when /^4168882222/  then
      sys.log("Rejecting call from #{req.Header.From.FromURI.User}")
      sys.Respond(488, "Your call is not welcome")
when /^8883334545/  then
      sys.Log("Rejecting call from #{req.Header.From.FromURI.User}")
      sys.Respond(488, "Your call is not welcome")
when /^4162223333/  then
      sys.Log("Forwarding call from #{req.Header.From.FromURI.User} to Mobile")
      sys.Dial("14169392323@Provider1")





Code: Select all
else


Code: Select all
#****Route calls based on Trunk Only****

case trunk
when /provider3.mssuser/ then           
    sys.Log("Initiating Call Forward-1")
    sys.dial("**466@PhoneGnome")
when /provider5.mssuser/ then         
  sys.Log("Initiating Call Forward-2")
  sys.dial("14169392424@Provider1")


Code: Select all
else


Code: Select all

#****Have Calls Ring ATA or Forward if Offline****

sys.Log("Accepting Call")
   
   if sys.IsAvailable() then
          sys.Log("The ATA is online.")
          sys.Dial("local")
      else
          sys.Log("The ATA is off-line.")
          sys.Dial("165528@us.voxalot.com") 
   end


Code: Select all
#****End Statements****

end #cid+trunk rule 1
end #cid+trunk rule 2

end #case trunk
end #case cid


Code: Select all
else



#********Outgoing Calls********

Code: Select all
sys.log("***Outgoing Call Starting***")
number_called = req.URI.User


Code: Select all
#****Block Calls to certain numbers****

case number_called
when /^1900/
     sys.Log("Call to #{req.URI.User} not allowed")
     sys.Respond(488, "Call not allowed")
when /^900/
     sys.Log("Call to #{req.URI.User} not allowed")
     sys.Respond(488, "Call not allowed")


Code: Select all
else


Code: Select all
#****Adjust for 7 digit and 10 digit Dialing****

number_length = req.URI.User.Length.to_s
sys.log("Number is #{number_length} digits long")

case number_length
when /^7/
     sys.Log("Local Call to 416#{req.URI.User}")
     sys.Dial("1416${dst}@Provider1")
when /^10/
     sys.Log("National Call  to 1#{req.URI.User}")
     sys.Dial("1${dst}@Provider1")


Code: Select all
else


Code: Select all
#****Outgoing Dial Plans****

case number_called
when /^\*1/
      sys.Log("Dialing #{req.URI.User} via Provider1.")
      sys.Dial("${dst:2}@Provider1")
when /^\*2/ then
      sys.Log("Dialing #{req.URI.User} via VoXPG.")
      sys.Dial("${dst:2}@Provider2")
when /^\*500/ then
      sys.Log("Dialing VoXalot VoiceMail.")
      sys.Dial("*010*500@sipbroker.com")
when /^1/ then
      sys.Log("Dialing North American Number #{req.URI.User}.")
      sys.Dial("Provider1")
when /^011/ then
      sys.Log("Dialing International Number #{req.URI.User}.")
      sys.Dial("Provider2")


Code: Select all
else


Code: Select all
#****If there is no other match****

sys.Log("No Dial Plan Match: Trying Default Rule")
sys.Dial("VoXalot")


Code: Select all
#****End Statements****

end  # case for outgoing dialplans
end  # case for number length
end  # case for blocked numbers
end


2. Regular Expression examples for Ruby

This is to further help as you write your own Ruby plan:

Example 1

Regular Syntax:
exten => _*1X.,1,Switch(${EXTEN:2}@provider)

Can be written in Ruby within a case statement as:

Code: Select all
when /^\*1/ then sys.Dial("${dst:2}@provider")

or

when /^\*1.*$/ then sys.Dial("${dst:2}@provider")

or

when /\*1.*/ then sys.Dial("${dst:2}@provider")


or within an if statement as:

Code: Select all
if req.URI.User.StartsWith("*1") then
sys.Dial("${dst:2}@provider")
end


Example 2

Regular Syntax:
exten => _11X.,1,Switch(${EXTEN:2}@provider)

Can be written in Ruby within a case statement as:

Code: Select all
when /^11/ then sys.Dial("${dst:2}@provider")

or

when /^11.*$/ then sys.Dial("${dst:2}@provider")

or

when /11.*/ then sys.Dial("${dst:2}@provider")


or within an if statement as:

Code: Select all
if req.URI.User.StartsWith("11") then
sys.Dial("${dst:2}@provider")
end


Example 3

Regular Syntax:
exten => _12,1,Switch(12@provider)

can be written in Ruby as:
Code: Select all
when /^12$/ then sys.Dial("12@provider")


See https://www.mysipswitch.com/forum/viewtopic.php?t=579

Example 4

Regular Syntax:
exten => _13.,1,Switch(${EXTEN:2}@provider)

Can be written in Ruby as:
when /^13.*$/ then sys.Dial("${dst:2}@provider")


Regular Syntax
exten => _13x.,1,Switch(${EXTEN:2}@provider)

Can be written in Ruby as:
when /^13.+$/ then sys.Dial("${dst:2}@provider")


Regular Syntax
exten => _13xxxx,1,Switch(${EXTEN:2}@provider)

Can be written in Ruby as:
when /^13.{4}$/ then sys.Dial("${dst:2}@provider")

See https://www.mysipswitch.com/forum/viewtopic.php?t=598
emoci
 
Posts: 125
Joined: Mon Aug 20, 2007 11:27 pm

Postby gbonnet » Mon Jul 14, 2008 7:18 am

Thanks a lot for that Emoci !
Blueface Phone Service
gbonnet
Site Admin
 
Posts: 681
Joined: Wed Jul 11, 2007 2:58 pm
Location: Bologna

Postby TheFug » Sun Jul 20, 2008 10:21 am

Some nice examples ! but if i understand correctly, with all these examples. the first 2 digits or not dialled out ? what if i want to dial out all keyed in digits ?
I want to convert my dialplan to Ruby:

exten =~ ^(8|613|612|958|514),1,Switch(FWD)
exten =~ ^(1800|1866|1877),1,Switch(*${EXTEN}@FWD)
exten => _08X.,1,Switch(*318${EXTEN:2}@FWD)
exten => _1777X.,1,Switch(CALLCENTRIC)
exten => _*75X.,1,Switch(*75${EXTEN:3}@CALLCENTRIC,true)
exten => _*1X.,1,Switch(${EXTEN:2}@BRUJULA)

Do i need to make something for my incoming calls also, if all incoming calls should go to my MSS account ?
Thanks, The Fug.

gear: Sitecom modem DC223/DC227†,301 D -gigaset DECT IP basestation. some switches, and a snom820 IP phone
User avatar
TheFug
 
Posts: 907
Joined: Sat Oct 06, 2007 8:23 am
Location: The Netherlands, North-Holland

Postby Aaron » Sun Jul 20, 2008 11:52 am

Hi TheFug,

Based on what you have there a Ruby equivalent Ruby dial plan would be

Code: Select all
sys.Log("call received on #{req.URI.ToString()} from #{req.Header.From.FromURI.ToString()} at #{Time.now}.")

if sys.Out then
sys.Log("Outgoing call from user domain=#{sys.FromDomain}.")
case req.URI.User
  when /^(8|613|612|958|514)/ then sys.Dial("FWD")
  when /^(1800|1866|1877)/ then sys.Dial("*${dst}@FWD")
  when /^08/ then sys.Dial("*318${dst:2}@FWD")
  when /^1777/ then sys.Dial("CALLCENTRIC")
  when /^\*75/ then sys.Dial("*75${dst:3}@CALLCENTRIC")
  when /^\*1/ then sys.Dial("${dst:2}@BRUJULA")
end
else
sys.Log("Incoming call to domain=#{sys.ToDomain} from host #{req.Header.From.FromURI.Host}.")
if sys.IsAvailable() then
   sys.Log("#{sys.Username} is online.")
   sys.Dial("#{sys.Username}@local")
else
   sys.Log("#{sys.Username} is not online.")
   sys.Respond(480, "#{sys.Username} Not online")
end
end


Regards,

Aaron
User avatar
Aaron
Site Admin
 
Posts: 2547
Joined: Thu Jul 12, 2007 12:13 am

Postby TheFug » Sun Jul 20, 2008 2:08 pm

It didn't worked the first time because i forgot to add .....#Ruby...... stupid me :)

And now it stopped, i hear a 3 tone response in the handset...
I guess i made a start now, with Ruby, i let it rest for now, i'll pick it up ..monday, with a fresh start...
Thanks, The Fug.

gear: Sitecom modem DC223/DC227†,301 D -gigaset DECT IP basestation. some switches, and a snom820 IP phone
User avatar
TheFug
 
Posts: 907
Joined: Sat Oct 06, 2007 8:23 am
Location: The Netherlands, North-Holland

Postby TheFug » Sun Jul 20, 2008 2:55 pm

TheFug wrote:It didn't worked the first time because i forgot to add .....#Ruby...... stupid me :)

And now it stopped, i hear a 3 tone response in the handset...
I guess i made a start now, with Ruby, i let it rest for now, i'll pick it up ..monday, with a fresh start...



Well, i noticed some other things where not working also, so i restarted everything, pc, modem, C450IP, and YES ! it works perfect with the Ruby dialplan ! thankyou, Aaron ! this is great !
This opens a new door to more advanced features i had in mind....
Thanks, The Fug.

gear: Sitecom modem DC223/DC227†,301 D -gigaset DECT IP basestation. some switches, and a snom820 IP phone
User avatar
TheFug
 
Posts: 907
Joined: Sat Oct 06, 2007 8:23 am
Location: The Netherlands, North-Holland

Postby TheFug » Tue Jul 22, 2008 9:49 pm

Thank you, for your help Aaron, made some additions on what you gave me,
and it now looks like this:
Code: Select all
#Ruby
sys.Log("call received on #{req.URI.ToString()} from #{req.Header.From.FromURI.ToString()} at #{Time.now}.")

if sys.Out then
sys.Log("Outgoing call from user domain=#{sys.FromDomain}.")
case req.URI.User
  when /^(8|613|612|958|514)/ then sys.Dial("FWD")
  when /^(1800|1866|1877)/ then sys.Dial("*${dst}@FWD")
  when /^(0|00)/ then sys.Dial("${dst}@INTERVOIP")
  when /^08/ then sys.Dial("*318${dst:2}@FWD")
  when /^1777/ then sys.Dial("CALLCENTRIC")
  when /^\*75/ then sys.Dial("*75${dst:3}@CALLCENTRIC")
  when /^\*1/ then sys.Dial("${dst:2}@BRUJULA")
  when /^\*2/ then sys.Dial("${dst:2}@SIPGATE")
  when /^\*3/ then sys.Dial("${dst:2}@ORBTALK")
  when /^\*4/ then sys.Dial("${dst:2}@FWD")
  when /^\*5/ then sys.Dial("${dst:2}@IXCALL")
  when /^\*6/ then sys.Dial("${dst:2}@VOXALOT")
  when /^\*7/ then sys.Dial("${dst:2}@CALLCENTRIC")
end
else
sys.Log("Incoming call to domain=#{sys.ToDomain} from host #{req.Header.From.FromURI.Host}.")
if sys.IsAvailable() then
   sys.Log("#{sys.Username} is online.")
   sys.Dial("#{sys.Username}@local")
else
   sys.Log("#{sys.Username} is not online.")
   sys.Respond(480, "#{sys.Username} Not online")
end
end



For some providers, i want to have a SIPtrace function switched on,
have searched for this in the older posts, but couldn't find it,
can this be done per provider ?
Thanks, The Fug.

gear: Sitecom modem DC223/DC227†,301 D -gigaset DECT IP basestation. some switches, and a snom820 IP phone
User avatar
TheFug
 
Posts: 907
Joined: Sat Oct 06, 2007 8:23 am
Location: The Netherlands, North-Holland

Postby gbonnet » Tue Aug 05, 2008 6:06 pm

Hi all,

I posted a quick guide about the default dial plan in Ruby :

The Default Ruby Dial Plan Demystified

HTH
Guillaume
Blueface Phone Service
gbonnet
Site Admin
 
Posts: 681
Joined: Wed Jul 11, 2007 2:58 pm
Location: Bologna

Postby TheFug » Tue Aug 05, 2008 7:57 pm

Thanks for that ! this makes me to understand it better, and make easy adjustments. (the /^\ ...)
Thanks, The Fug.

gear: Sitecom modem DC223/DC227†,301 D -gigaset DECT IP basestation. some switches, and a snom820 IP phone
User avatar
TheFug
 
Posts: 907
Joined: Sat Oct 06, 2007 8:23 am
Location: The Netherlands, North-Holland

Postby emoci » Sun Aug 17, 2008 12:47 am

Available Ruby Modules

(for more see http://www.mysipswitch.com/forum/viewtopic.php?t=399 )

CallBack Module

sys.Callback(string dest1, string dest2) - Initiates a call to dest1 and if successful then calls dest2 and bridges the calls together. The dest1 and dest2 parameters are SIP Provider constructs.
Code: Select all
# Ruby dialplan example for sys.Callback
sys.Log("call received uri=#{req.URI.User}")
sys.Callback("012345@blueface", "023456@voipstunt")



sys.Callback(string dest1, string dest2, int delay) - After specified delay, it initiates a call to dest1 and if successful then calls dest2 and bridges the calls together. The dest1 and dest2 parameters are SIP Provider constructs.
Code: Select all
# Ruby dialplan example for sys.Callback
sys.Log("call received uri=#{req.URI.User}")
sys.Callback("012345@blueface", "023456@voipstunt" , 10)


Dial Module

A note about the sys.Dial () function.

It can be used in a few forms:

-sys.Dial("ProviderName")

When used in this form, the number called via the specified provider by default is the value stored in the variable req.URI.User

When you are placing a call, req.URI.user is the number you're calling.
When an incoming call is coming in, req.URI.user is your account or subaccount username.

-sys.Dial("1${dst}@ProviderName")

This form is more useful when used for outgoing call routing, allowing one to modify how the number you've dialed is actually dialed via the specified provider. In this case ${dst} is the actual number as you dialed it.


sys.Dial(string provider) - The provider parameter must match a SIP Provider name.

The Dial command will forward the number as dialed to the SIP Provider.
Code: Select all
# Ruby dialplan example for sys.Dial
sys.Log("call received uri=#{req.URI.User}")
sys.Dial("ProviderName")


The Dial command will forward the number with modifications (eg. add 1 to front) to the SIP Provider.
Code: Select all
# Ruby dialplan example for sys.Dial
sys.Log("call received uri=#{req.URI.User}")
sys.Dial("1${dst}@ProviderName")


sys.Dial(string provider, int timeout)- Dial number, and if there is no answer after specified length of time (in seconds) then move to the next command
Code: Select all
# Ruby dialplan example for sys.Dial
sys.Log("call received uri=#{req.URI.User}")
sys.Dial("Provider1", 10)
sys.Dial("Provider2", 10)
sys.Dial("Provider3", 10)

Number modification can also be applied (to adjust number entered based on requirements of each provider):
eg.
Code: Select all
sys.Dial("1${dst}@Provider1", 10)
sys.Dial("00${dst}@Provider2", 10)
sys.Dial("${dst:3}@Provider3", 10)


sys.Dial(string number@provider&string number2@provider)- Simultaneous calls to two or more destinations
Code: Select all
# Ruby dialplan example for sys.Dial
sys.Log("call received uri=#{req.URI.User}")
sys.Dial("Number@Provider1&Number2@Provider1&Number3@Provider2)


sys.Dial(provider1|provider2|provider3)- Number called is passed to the first provider, should it fail, the call is attempted over the second provider, then the third and so on (for those familiar with Asterisk terms, this is the equivalent of FallBack Trunks).
Code: Select all
# Ruby dialplan example for sys.Dial
sys.Log("call received uri=#{req.URI.User}")
sys.Dial("Provider1|Provider2|Provider3)

Number modification can also be applied (to adjust number entered based on requirements of each provider):
eg.
Code: Select all
sys.Dial("1${dst}@Provider1|00${dst}@Provider2|${dst:3}Provider3")


sys.RegexMatch (variable, "value-to-match") - A matching statement to check the value of the specific variable. Should the match be 'True' then other actions can be allowed to occur when this is part of an if statement.
Code: Select all
if sys.RegexMatch(req.URI.User, "skype.mocierion")   then
sys.log("Other modules can be added here, like sys.Dial or sys.Callback")


During and Incoming Call

req.URI.User = The Username of the MSS acct. receiving the call (this the username of your acct., or sub-account, or 'anything.mssuser', if it is a call for anything.mssuser@sip.mysipswitch.com)
req.URI.Host = The host portion of the URI for which the call is coming in (eg. sip.mysipswitch.com or the corresponding IP)

req.Header.From.FromName = Name of Caller
req.Header.From.FromURI.User = Number of Caller (or their username if the call is coming from another MSS or VoIP user )
req.Header.From.FromURI.Host = The Host of the caller (this is usually an IP adress that indentifies the provider your caller is using to call you)

During an Outgoing call

req.URI.User = Number you are calling

req.Header.From.FromURI.User = Your account username (account doing the calling)
req.Header.from.FromURI.Host = Your provider with which you're registering (this is usually the IP for sip.mysipswitch.com )
req.Header.From.FromName = Your Name

Adjusting Outgoing Caller ID:
(this is one way to adjust the outgoing CID, you can also make modifications to the 'From Header' field when setting up a provider)

During an outgoing or Forwarded Call, you can adjust the three fields above to set your customize your Caller ID.

eg.
Code: Select all
req.Header.From.FromURI.User = "01234567"
req.Header.from.FromURI.Host = "mydomain.com"
req.Header.From.FromName = "Joe Bloggs"


The above script would result in a From header of:

From: "Joe Bloggs" <sip:01234567@mydomain.com>

But PLEASE NOTE that the field that is generally used for authentication is req.Header.From.FromURI.User so be aware your calls could fail if it is modified.
emoci
 
Posts: 125
Joined: Mon Aug 20, 2007 11:27 pm

PreviousNext

Return to Technical Support

Who is online

Users browsing this forum: No registered users and 0 guests