Sending a Command to Your Dial Plan

Catalog of dial plans
jack9901
Posts: 277
Joined: Tue Jan 29, 2008 7:30 pm

Sending a Command to Your Dial Plan

Post by jack9901 » Sun Aug 17, 2008 8:43 am

The string(or number) you dial usually is the number you want to reach with some prefix. With Ruby, you can also make the string you dial a command that you want your dial plan to execute, e.g. you can trigger the sys.Callback function and connect two calls with the following code:

Code: Select all

dst_num0 = req.URI.User.to_s
if dst_num0 =~ /^\*\*8(.+)/   # **8, command to bridge two calls
   dst_num0 = $1.gsub(/\*\*/, "|")
   dst_num0 =~ /^([^|]+)([|]([^|]*))?([|]([^|]*))?/
   dst_num0 = $1
   ($3 && ($3 != ""))? (dst_num1 = $3) : (dst_num1 = dst_num0; dst_num0 = default_callback_number)
   delay = $5.to_i
   sys.Callback(dst_num0+"@provider", dst_num1+"@provider", delay)
end
The above code snippet will implement a callback command in the following format:

Code: Select all

**8First_number**Second_number**Delay
where both the Second_number and the Delay are optional. e.g.

"**8First_number" triggers sys.Callback(default_callback_number, First_number, 0)
"**8First_number****12" triggers sys.Callback(default_callback_number, First_number, 12)
"**8First_number**Second_number" triggers sys.Callback(First_number, Second_number, 0)

Similarly, you can use **1, **2 or any prefix to initiate a command you want to execute. If Aaron were to implement personal storage or non-volatile varibles for personal use, you will be able to change your dial plan on the fly. i.e. you can use your softphone, or use PSTN dial in or callback to connect to an IVR, to dial a command string that will trigger a callback to arbitrary numbers or change anything in your dial plan such as default local outbound provider, default international outbound provider, default callback number, etc. That will be really cool, instead of finding some place to log on the sipswitch web site to change your dial plan.

In the mean time, instead of hearing dead air when you dial a command, if you want to get some audible feedback to confirm that your command is going to be or have been executed, you can insert the following code or the similar in your command processing:

Code: Select all

   sys.Dial(",,*4621777xxxxxxx@sipbroker.com,<sip:0000000@sipbroker.com>", 2)   # give some audible feedback
where *462 is the sipbroker code for Callcentric and 1777xxxxxxx is my Callcentric account number. In my Callcentric account, the call treatment is set to give an error message when the caller ID is 0000000. The 2 seconds limit in the sys.Dial will be about long enough to give you a prompt "welcome to Callcentic" then cut off. So when you hear this, you know your command is being processed by mysipswitch. I use *4621777xxxxxxx@sipbroker.com instead of 1777xxxxxxx@in.callcentric.com because mysipswitch currently cannot resolve in.callcentric.com.

Hope the above can add a grain of salt for advanced users.

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Post by MikeTelis » Mon Aug 18, 2008 6:57 am

Jack,

I hope you'll find my version more readable:

Code: Select all

dst_num0 = req.URI.User.to_s 

case dst_num0		# Main parser
  when /^\*\*(.)(.*)$/ 	# **x commands
  
    parms = $2.split('**')	# Parse command parameters
    
    case $1			# **x command parser

      when "8"		# **8
        dst_num0 = parms[0]
        dst_num1 = (parms[1].to_s.empty?)? default_callback_number : parms[1]
        delay = parms[2].to_i
        sys.Callback(dst_num0+"@provider", dst_num1+"@provider", delay)
        
    end		# **x parser
end		# Main parser
Of course, it's possible to do without dst_num0, dst_num1 and delay assignments and put correspondent parameters right into the sys.Callback method call.

Now, could you please explain the use scenario for all this? I mean, to send commands to MSS and hear voice response you must have a good Internet connection. If so, why do you need to callback at all? You could have called your destination number directly and pay for one leg only...

jack9901
Posts: 277
Joined: Tue Jan 29, 2008 7:30 pm

Post by jack9901 » Mon Aug 18, 2008 8:25 pm

Hi Mike,

That makes a good use of the split method by replacing the inscrutable regular expression. One thing I would suggest is to keep the

sys.Callback(default_callback_number, the_other_number)

instead of replacing it with

sys.Callback(the_other_number, default_callback_number)

when dealing with dest_num1. Because when the first call leg is picked up, sys.Callback is then trying to reach the second leg. Before the second leg is connected, the person on the first leg hear nothing but dead air. And he probably will feel weird and hang up the call before the second leg can be connected after maybe 8 seconds. If the sipswitch user who initiates the callback is on the first call leg(default_callback_number), the silence does not matter because he knows he is using the callback function.

There are various occasions a callback command (or other commands if with personal storage) will be useful when you are away from home or office.

1. You have a poor internet connection that cannot maintain a VOIP call. You can use your softphone to send the callback command to make calls over PSTN with cheap providers in your dial plan.

2. You are only allowed to or you can only use the web browser. Voxalot and PBXes.org have some kind of CallMe UI's where othere people can enter a number and the server will call that number and then connect it to your SIP account or a specified number. Well, I can simply enter a **8**8First_number**Second_number in the number box to callback any two numbers via sipswitch. The first **8 is to tell Voxalot to use mysipswitch trunk and it is then stripped off, and the request of **8First_number**Second_number is sent to my sipswitch account to be processed. So you are really not using the CallMe function of Voxalot but use one of its legs to send command to mysipswitch. Mysipswitch has a similar page "Click to call" where you need to provide details of the provider and only one provider is allowed.

3. You do not have internet access, you have a land line that does not have long distance or international access to trigger the callback function, and you have a cell phone that can trigger the callback function but you want to be call back on the land line instead because of the price on the cell minutes.

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Post by MikeTelis » Tue Aug 19, 2008 3:37 am

Jack,

thank you very much for this detailed explanation. Indeed, on some occasions callback is very useful.

I have a couple of more questions, if you don't mind:

1. Where did you learn about the "delay" parameter of sys.Callback method? Aaron's topic on Ruby dialplan doesn't say anything about it...

2. Are there any other undocumented parameters? In particular, I'm wondering if there is a way to choose between re-invite and blind transfer.

elwebmaster
Posts: 20
Joined: Mon Jul 07, 2008 9:48 pm

Post by elwebmaster » Tue Aug 19, 2008 5:11 pm

How do you actually trigger the execution of the script? Do you just put it in the inbound part of the dial plan and call your MSS username? Or is it supposed to be put in the outbound and you have to send the command as if you were dialing out?
Can you please give some more details regarding the implementation?
Can you use SipBroker for example to call your MSS script, enter the command, hang up and wait for the callback? Or do you need a calltrough that would "dial" the command string using MSS?

jvwelzen
Posts: 716
Joined: Thu Sep 11, 2008 1:56 pm

Post by jvwelzen » Fri Oct 10, 2008 11:15 am

I am not getting this to work on my local version

when i call **731357110000**3164966234567**5

Intervoip gives error 404

and I don't see the callback function starting

It only sends the whole string to intervoip


# Call *7 For Callback Function.
dst_num0 = req.URI.User.to_s
if dst_num0 =~ /^\*\*7(.+)/ # **7, command to bridge two calls
dst_num0 = $1.gsub(/\*\*/, "|")
dst_num0 =~ /^([^|]+)([|]([^|]*))?([|]([^|]*))?/
dst_num0 = $1
($3 && ($3 != ""))? (dst_num1 = $3) : (dst_num1 = dst_num0; dst_num0 = default_callback_number)
delay = $5.to_i
sys.Callback(dst_num0+"@intervoip-#{sys.Username}", dst_num1+"@intervoip-#{sys.Username}", delay)
end

Any idea why this is not working

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Post by MikeTelis » Fri Oct 10, 2008 2:30 pm

I guess these are not the first lines in the "outbound" part of your dialplan. So, scroll up and look for sys.Dial executed prior to this code.

I personally tested Jack's code (nevermind my version) and it works. So, if something goes wrong it means you never reach Jack's code because of some bug in the logic of your dialplan.

jvwelzen
Posts: 716
Joined: Thu Sep 11, 2008 1:56 pm

Post by jvwelzen » Fri Oct 10, 2008 4:53 pm

Yep That works

I have put it on top of the dialplan and it is working

Thanks Mike

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Post by MikeTelis » Fri Oct 10, 2008 5:04 pm

You need to find the code intercepting **7 command in the first place. There's a good chance that this code isn't working now that you moved **7 handler to the beginning of your program.

Mike

jvwelzen
Posts: 716
Joined: Thu Sep 11, 2008 1:56 pm

Post by jvwelzen » Sat Oct 11, 2008 10:10 am

It is working

But I am still learing ruby over here

I was trying to use a piece of your script to replace the 0 with the country code an I tought it was working but sudenly it was not working anymore

Maybe you have an idea why ?

This is the dialplan :

#Ruby

LandNummer = "31"

sys.Log("### call from #{req.Header.From.FromURI.ToString()} to #{req.URI.User}. ###")

if sys.In then

# Do your incoming and forwarding call processing here.
sys.Dial("#{sys.Username}@sip.huizenwireless.nl", 35)
else

# Do your outgoing call processing customisations here. (PhoneBook)

# MikeTelis Piece of Code
case @num

when /^0/
@num = "31" # Replace 0 to LandNummer for the Netherlands

end

case req.URI.User

when /^612$/ then sys.Dial("612@fwd.pulver.com") # Speaking Clock
when /^613$/ then sys.Dial("613@fwd.pulver.com") # Echo Test

# Call 0800 Numers in the netherlands trough poivy. (this is free)
when /^8/ then sys.Dial("#{@num}${dst:1}@poivy-#{sys.Username}")

# Call local (Huizen Wireless) e164.org internet Numbers.
when /^88299007689/ then
req.Header.From.FromName = "#{sys.Username}"
sys.Dial("#{req.URI.User}@sip.huizenwireless.nl")

# Do ENUMLookup for 88299 e164.org internet numbers.
when /^88299/ then
enumURI = "" unless enumURI = sys.ENUMLookup("+#{req.URI.User.to_str[1..-1]}.e164.org").to_s
if enumURI.empty?

# If no ENUMLookup found for 88299 e164.org internet numbers call default outgoing line.
sys.Dial("#{@num}${dst}@intervoip-#{sys.Username}")
else

# If ENUMLookup for 88299 e164.org internet number found call ENUM Uri.
sys.Dial("#{enumURI}")
end

# Call voipcheap/backup line for freedays or backup with *1
when /^\*1/ then sys.Dial("#{@num}${dst:2}@voipcheap-#{sys.Username}")

# Use *8(Number) for callback fuction
when /^\*8/ then sys.Callback("#{sys.Username}@sip.huizenwireless.nl", "#{@num}${dst:2}@intervoip-#{sys.Username}", 10)

# Force ENUMLookup for normal numbers with *9
when /^\*9/ then
enumURI = "" unless enumURI = sys.ENUMLookup("+#{@num}#{req.URI.User.to_str[1..-1]}.e164.org").to_s
if enumURI.empty?

# If no Forced ENUMLookup number found call default outgoing line.
sys.Dial("#{@num}${dst:2}@intervoip-#{sys.Username}")
else

# If Forced ENUMLookup number found call ENUM Uri.
sys.Dial("#{enumURI}")
end

else
sys.Dial("#{@num}${EXTEN}@intervoip-#{sys.Username}")
end
end

Post Reply