Emulating Shared Lines in Asterisk
The term "shared lines" in Asterisk means implementing the functionality of having a line appearance on a phone that maps to a trunk. So, multiple phones can have a "line1" appearance that is mapped to a SIP trunk, for example. Then, when any phone is using this line, the line shows as in use on all of the other phones.
So, after enough demand for this feature, we decided that we would commit to making a way to set up an Asteirsk system to work like a key system. There was a version of this support in Asterisk 1.4.0. However, it didn't really work. So, before 1.4.1 was released, I completely re-wrote the SLA support for Asterisk. Now, it works!
Implementing this feature in Asterisk was an interesting challenge. In the case of a traditional analog PBX, there are physical phone lines that can be mapped to lines on the phone. However, in the case of Asterisk, the "trunk" on the key system could be an analog FXO line, or another Asterisk channel type, such as a connection to a SIP provider. So, all of the connections between trunks and stations are all "virtual".
Let me try to explain a bit of how it works ...
Configuration Overview
The first step to making this work is defining mappings between virtual trunks and virtual stations to Asterisk channels. This is done in sla.conf. For example, this defines a couple of "trunks" to this virtual key system to Asterisk channels, which happen to be 3 FXO lines here:
[line1] type=trunk device=Zap/1 [line2] type=trunk device=Zap/2 [line3] type=trunk device=Zap/3
To create virtual stations, we have to map it to an Asterisk channel as well as define which virtual trunks this station will use. The stations are SIP phones in this case:
[station1] type=station device=SIP/station1 trunk=line1 trunk=line2 [station2] type=station device=SIP/station2 trunk=line1 trunk=line2 [station3] type=station device=SIP/station3 trunk=line1 trunk=line2
The next step is configure the Asterisk channels themselves (Zap/1, SIP/station1, etc.). This would be done in zapata.conf and sip.conf. These channels would be configured as normal for the most part. The only part I want to note is that for the examples here, the "context" for the Zap channels would be configured to "line1", "line2", and "line3". The "context" setting in sip.conf for all of the stations would be "sla_stations". This makes incoming calls from each trunk go their own context, and incoming calls from the phones to all go to the context "sla_stations".
Now, the interface between calls coming into Asterisk and the SLA emulation layer in Asterisk is built in the dialplan (extensions.conf). Before I get there, let me explain the goals of the SLA dialplan applications.
The SLA code monitors what is happening on all of the virtual trunks and stations. The logic controls:
- If a phone is in use, it determines which trunk it should be connected to.
- If a phone is not in use:
- It controls whether the phone should be ringing or not.
- It controls what the light for each virtual trunk should be showing.
The interesting thing to note is that the control of phones ringing is not tied to making the lights blink. The phone does not perform any of this magic to associate calls to each virtual trunk. To look a little bit closer, let's start with some of the dialplan.
[line1] exten => s,1,SLATrunk(line1) [line2] exten => s,1,SLATrunk(line2) [line3] exten => s,1,SLATrunk(line3)
The previous dialplan snippet is what happens in the dialplan when any call comes in on one of the FXO lines. It immediately runs the "SLATrunk" application with an argument that indicates which virtual trunk is calling.
Inside of the SLA trunk trunk application, the SLA layer checks all of the stations that use this trunk to see if they are already ringing or in use. If it is not, it will make the phone start ringing. In addition to this, it sets some special state information which then makes the light for that line start blinking on the phone. Once one of the phones answer, they are connected in a conference, the other phones stop ringing if they don't have any of their other lines ringing, and all of the phones' lights for that line show the line as in use.
Now, let's look at what is in the dialplan that makes the interface to the stations work. In this, I am only showing the part for station1. However, the same dialplan information would be the same for other stations, as well:
[sla_stations] exten => station1,1,SLAStation(station1) exten => station1_line1,1,SLAStation(station1_line1) exten => station1_line2,1,SLAStation(station1_line2) exten => station1_line3,1,SLAStation(station1_line3) exten => station1_line1,hint,SLA:station1_line1 exten => station1_line2,hint,SLA:station1_line2 exten => station1_line3,hint,SLA:station1_line3
There are really two different types of entires in the example shown above, which separated by a blank line.
The first 4 lines define what happen when a call comes in from a station. There are 4 extensions here because the behavior is different based on how the phone initiated the call. If the phone is just taken off hook, it calls the SLAStation application with the argument "station1". However, if the call is initiated by the user pressing the line1 button, then the SLAStation application is calling with an argument of "station1_line1". This tells the SLA core that the line1 button was pressed.
If the phone calls "station1", the SLA core will then find the first trunk that is not in use, take it off hook, and put it in a conference with the phone. Then, it would make all of the lights on phones that show "line1" show that the line is in use.
If the phone calls "station1_line1", the SLA core will just drop the call into the existing conference with the other phones that are already on the call on that line. (This can be prevented using a configuration option, but that's not the point, here).
The second set of entries in the previous dialplan snippet are the "hints". This is the magic entry in the dialplan that lets the phones monitor the state of each virtual "trunk" on the system. In the configuration of the SIP phone itself, you would configure a button (sometimes called BLF) to subscribe to the state of extensions "station1_line1", "staiton1_line2", and "station1_line3". This is what allows the SLA core to control what the lights on the phone reflect.
Some Final Notes
So, there it is. You can now go give a fancy brand new Asterisk system that includes some key system functionality. It is even possible to use all VoIP for this setup. Both the stations and trunks can be SIP. Using SIP trunks has a little bit extra configuration, but it is documented.
For more information, look at the following files in the Asterisk 1.4 source tree:
- configs/sla.conf.sample
- doc/sla.pdf
Feel free to report any problems to http://bugs.digium.com/.
