Overview
One of the topics of discussion every year at Astricon is not needing to use the dialplan in order to use Stasis. This involves a couple of different things in order to bypass dialplan completely. First of all, the only way to enter Stasis is to have a line of dialplan that places the channel in it, like so:
exten => 123,1,Stasis(my-app)
Secondly, once a channel is in Stasis, there is no way for that channel to enter another application without first leaving the application it’s in and entering dialplan once more. This can be pretty restrictive for people who want to have a separation from Asterisk and program in a language they’re comfortable with, so we decided to implement these new features with the release of Asterisk 13.26.0 and 16.3.0.
Automatic Context Creation
This change could easily fly under the radar if you didn’t know about it. But that’s a good thing! We wanted to implement this in a way that would be as non-intrusive as possible. Look at the the one-line dialplan extension above. Say you have an application called “my-app”. Now, you could go into extensions.conf and add this line to your dialplan if you’d like, but that is no longer necessary. When you launch your application, Asterisk will now automatically create a context and extension for you that will allow your endpoints to access Stasis. Internally, it will look like this:
[stasis-my-app] exten => _.,1,Stasis(my-app) exten => h,1,Hangup()
Your endpoint is required to have this context, but now any calls made from that endpoint will go to your Stasis application “my-app”. If the context already exists, a message will be displayed on the Asterisk CLI to let you know, and nothing will be done.
Moving Between Applications
So we don’t need dialplan anymore to enter our Stasis applications. That’s great, but what about switching applications? What about my application arguments? Don’t worry! You can move from any application you’re in to any application you’d like! The syntax is very simple. Say we had an application named “ari-example1” and “ari-example2”. Both of these applications are active. Our channel enters “ari-example1”, but now we would like it to be in “ari-example2”. How do we do this? Take a look at the following example:
#!/usr/bin/env python import ari client = ari.connect('http://localhost:8088', 'asterisk', 'asterisk') def stasis_start_cb(channel_obj, ev): channel = channel_obj.get('channel') print "Channel {0} has entered the application".format(channel.json.get('name')) channel.answer() print "Current channels:" current_channels = client.channels.list() for chan in current_channels: print chan.json.get('name') client.channels.move(channelId=channel.id, app='ari-example2', appArgs='some,example,args') def stasis_end_cb(channel, ev): print "{0} has left the application".format(channel.json.get('name')) client.on_channel_event('StasisStart', stasis_start_cb) client.on_channel_event('StasisEnd', stasis_end_cb) client.run(apps='ari-example1')
Here’s a really simple Stasis application written in Python. Whenever a channel enters, all channels in Stasis will be printed, and the entering channel will be moved from “ari-example1” to “ari-example2” with the arguments “some”, “example”, and “args”. Using this, you can now construct one master application that can move channels to the appropriate application!
One important thing to note is that things can go wrong, so you need to be able to handle errors if they occur. A new event “ApplicationMoveFailed” has been added that you can listen for in your applications to handle moves that didn’t work. This event contains the channel, the destination application, and the application arguments so you can decide what to do from there.
That’s all there is to it! Everything can be done from your Stasis application without you having to touch the dialplan at all.
One Response
Hello, it didn’t seems to work well with CEL. Move between applications didn’t produce the APP_START/APP_END events, I need to use continueInDialplan with another stasis application, or I am missing something ?