Recently, quite a lot of articles on asterisk appeared on Habré and in all articles the authors use standard extensions.conf to describe the dial plan. I will not describe here the format of the record in extensions.conf, but only try to briefly describe its differences with the configuration files in the AEL (extensions.ael) format, which are actually quite a bit, but the ael adds a lot of convenience. In the future, for convenience, the dial plan described in extensions.conf will be called the “normal” format, and ael, respectively, ael. Let's look at an example of the simplest dial plan in the usual format:
;
[internal]
exten => s, 1, Answer
exten => s, n, Background (someivr)
exten => s, n, Read (intgroup ,, 3)
exten => s, n, Goto ($ {intgroup}, 1)
exten => XXX, 1, Dial (SIP / $ {EXTEN})
exten => XXX, n, HangUp
And this is how the same context will look like in the ael syntax:
context internal {
s => {
Answer;
Background (someivr);
Read (intgroup ,, 3);
Goto ($ {intgroup}, 1);
}
XXX => {
Dial (SIP / $ {EXTEN});
HangUp;
}
}
So the differences are there. For me, one of the main advantages of ael is the convenience of reading the config: even in this small abstract example, it is clear that it is easier to read and understand the config. Although, I admit that this is subjective. The second thing that immediately catches the eye is the lack of priority (s,
n in the code above, though, as noted in the
comments , priority and there is no longer necessary) in the description of the dialplan.
Why aren't they? Or rather, why are they in the description of a normal dialplan?
If you have not dealt with this asterisk and with its usual dialplan, then you will be surprised to learn that there are no cycles or conditions in it. There is only a conditional transition (gotoif), with the help of which, in principle, even cycles can be organized, but the convenience of this approach is very doubtful. Let's imagine the simplest ael code that will output true or false to the asterisk console:
if ($ {var} = foo) {
NoOp (true);
}
else {
NoOp (false);
}
')
In its usual form, this condition will look like this:
exten => 1.1, GotoIf ($ [$ {var} = foo]? label1: label2)
exten => 1, n (label1), NoOp (true)
exten => 1, n, Goto (end_of_if)
exten => 1, n (label2), NoOp (false)
exten => 1, n (end_of_if), ...
Not only have we lost the “readability”, we are also forced either to statically prescribe priorities everywhere (and get absolutely non-extensible code), or to invent tags for every other thing. Yes, ael also has tags, only the need for them practically disappears, since the syntax allows you to get away from goto as such.
s => {
Answer;
somelabel:
HangUp;
}
In addition to the actual conditions (if / else) in ael, you can use the switch statement with the usual syntax:
_777X => {
switch ($ {EXTEN}) {
pattern N11:
NoOp (You called a N11 number-- $ {EXTEN});
break;
case 7771:
NoOp (You called 7771!);
break;
case 7772:
NoOp (You called 7772!);
break;
case 7773:
NoOp (You called 7773!);
// fall thru-
default:
NoOp (In the default clause!);
};
Now try to describe the same configuration, but in the usual format? That is the same.
Now imagine that you have a more or less complex dialplan, which will grow and expand over time, new functionality will be added, there will be many conditions, queues and so on - here without ael everything will be pretty sad. At work, from time to time you have to set up an asterisk and requests from clients are quite exotic. Solving these problems without ael would be much more difficult.
To be fair, it should be said that the asterisk converts the ael configuration into a “normal” format and already works with it (you can check it with asterisk -rx “dialplan show”), so its syntax is also necessary to know. But ael can make life much easier, especially as you can see, its syntax is pretty obvious, and if you have experience writing normal dial plans, it will be easy to switch to ael.