login | register
Wed 01 of Aug, 2007 [09:23 UTC]

voip-info.org

Search with Google
Search this site with Google. Results may not include recent changes.

Web www.voip-info.org
Shoutbox
  • Aykut, Wed 01 of Aug, 2007 [07:53 UTC]: Hi all, does anybody know about Thomson ST2030 SIP phone. I have upgraded it to latest version (1.56) but "Hold" and "Conf" features are not working after the upgrade ?? Do you know any solution or do you have Ver. 1.52 ?? Where can I find it?
  • Edward J Brown, Tue 31 of Jul, 2007 [23:33 UTC]: Has anybody experienced Choppy voice quality when using a Linksys SPA942 in an Asterisk Conference bridge? It works fine with my polycom and Cisco, but sucks with my Linksys.
  • www.astawerks.com, Fri 27 of Jul, 2007 [18:00 UTC]: does anyone use asterisk on top of clark connect? does it work good?
  • simon, Fri 27 of Jul, 2007 [14:16 UTC]: Hi All, Has anyone here managed to get the Cisco79x1 to successfully fail over to the backup proxy. I have 2 asterisk servers , handsets all register and function, except that backup proxy function doesn't work. Any working example would be very apprecia
  • Matthew Richmond, Thu 26 of Jul, 2007 [03:40 UTC]: using the page() application to page across our building...often the meetme conferences don't disconnect after the caller hangs up. Anyone else having this problem. (using Polycom phones)
  • Matthew Richmond, Wed 25 of Jul, 2007 [02:58 UTC]: thanks Nicholas Blasgen! I haven't worked with AGI before, but there's always a first! Thanks again!
  • Nicholas Blasgen, Tue 24 of Jul, 2007 [19:18 UTC]: Matthew Richmond, AGI will handle all that for you.
  • sam, Mon 23 of Jul, 2007 [16:39 UTC]: need help - certain voicemail extension will stop working and recording voicemail on asterisk - anyone know why and how to fix it? Thanks
  • john haji, Mon 23 of Jul, 2007 [14:55 UTC]: free calls to pakistan
  • bong, Sat 21 of Jul, 2007 [19:09 UTC]: hi good day to all can anyone help me how to configured the nortel sip to the signaling server and how to activate in mobile w/ sip compatible without mcs
Server Stats
  • Execution time: 0.24s
  • Memory usage: 2.27MB
  • Database queries: 32
  • GZIP: Disabled
  • Server load: 3.26

Asterisk AEL

  • Please note that AEL is still considered EXPERIMENTAL at this time.

The Asterisk Extension Language


Over time, people have been pushing to add features to extensions.conf to make it more like a programming language. AEL is intended to provide an actual programming language that can be used to write an Asterisk dialplan.


Getting Started

The AEL parser (pbx_ael.so) is completely separate from the module that parses extensions.conf (pbx_config.so). To use AEL, the only thing that has to be done is the module pbx_ael.so must be loaded by Asterisk. This will be done automatically if using 'autoload=yes' in /etc/asterisk/modules.conf. When the module is loaded, it will look for 'extensions.ael' in /etc/asterisk/. Both extensions.conf and extensions.ael can be used in conjunction with each other if that is what is desired. Some users may want to keep extensions.conf for the features that are configured in the 'general' section of extensions.conf.


Reloading extensions.ael

To reload extensions.ael, the following command can be issued at the CLI.

    *CLI> ael reload

Debugging


Enable AEL contexts debug
   *CLI> ael debug contexts 

Enable AEL macros debug
   *CLI> ael debug macros 

Enable AEL read debug
   *CLI> ael debug read

Enable AEL tokens debug
   *CLI> ael debug tokens 

Disable AEL debug messages
   *CLI> ael no debug



Context

Contexts in AEL represent a set of extensions in the same way that they do in extensions.conf.


context default {

};

NOTE: The opening curly-brace must appear as above. Moving it to the following line may have disastrous consequences!

Extensions

To specify an extension in a context, the following syntax is used. If more than one application is be called in an extension, they can be listed in order inside of a block.


context default {
    1234 => Playback(tt-monkeys);
    8000 => {
         NoOp(one);
         NoOp(two);
         NoOp(three);
    };
    _5XXX => NoOp(it's a pattern!);
};



Includes

Contexts can be included in other contexts. All included contexts are listed within a single block.


context default {
    includes {
         local;
         longdistance;
         international;
    };
};



Dialplan Switches

Switches are listed in their own block within a context.


context default {
    switches {
         DUNDi/e164;
         IAX2/box5;
    };
    eswitches {
         IAX2/context@${CURSERVER};
    };
};



Ignorepat

ignorepat can be used to instruct channel drivers to not cancel dialtone upon receipt of a particular pattern. The most commonly used example is '9'.


context outgoing {
    ignorepat => 9;
};


NOTE: The opening curly-brace must appear as above. Moving it to the following line may have disastrous consequences!

Variables

Variables in Asterisk do not have a type, so to define a variable, it just has to be specified with a value.

Global variables are set in their own block.


globals {
    CONSOLE=Console/dsp;
    TRUNK=Zap/g2;
};

NOTE: The opening curly-brace must appear as above. Moving it to the following line may have disastrous consequences!

Variables can be set within extensions as well.


context foo {
    555 => {
         x=5;
         y=blah;
         divexample=10/2
         NoOp(x is ${x} and y is ${y} !);
    };
};


NOTE: Asterisk beta1 parses assignments using a $[] wrapper as opposed to the more logical way of doing it like Set and SetVar work. In this example, I had ${ARG1} set to "SIP/x7065558529" sans-quotes and it flunked out.
NOTE: Another opinion: The $[ ] allow expressions to be used, and add extra power to the language. Read the README.variables about the requirements of $ expressions. In the following example, the SIP/x7065558529
                  should not be "sans quotes". So, the statement might have been entered:  requesting_channel="${ARG1}";    ( where the ""'s prevent the evaluation. )
NOTE: These things are wrapped up in a $[ ] expression: The while() test; the if() test; the middle expression in the for( x; y; z) statement (the y expression); Assignments — the right hand side, so a = b -> Set(a=$[b])

         requesting_channel=${ARG1}
ERROR: Oct 10 12:48:59 WARNING[19726]: ast_expr2.y:811 op_div: non-numeric argument
   — Executing Set("SIP/x7065558529-2afd", "requesting_channel=0") in new stack
FROM show dialplan:
 's' =>            1. Set(requesting_channel=$[ ${ARG1} ])       [pbx_ael]

But you can use Set and it works the old way.

         Set(requesting_channel=${ARG1})


Writing to a dialplan function is treated the same as writing to a variable.


context blah {
    s => {
         CALLERID(name)=ChickenMan;
         NoOp(My name is ${CALLERID(name)} !);
    };
}; 



Loops

AEL has implementations of 'for' and 'while' loops.


context loops {
    1 => {
         for (x=0; ${x} < 3; x=${x} + 1) {
              Verbose(x is ${x} !);
         };
    };
    2 => {
         y=10;
         while (${y} >= 0) {
              Verbose(y is ${y} !);
              y=${y}-1;
         };
    };
};


NOTE: The conditional expression (the "${y} >= 0" above) is wrapped in $[ ] so it can be evaluated.
NOTE: The for loop test expression (the "${x} < 3" above) is wrapped in $[ ] so it can be evaluated.

Conditionals

AEL supports if and switch statements. Note that if you have an else clause, you MUST place braces around the non-else portion of the if statement.


context conditional {
    _8XXX => {
         Dial(SIP/${EXTEN});
         if ("${DIALSTATUS}" = "BUSY") {
              Voicemail(${EXTEN}|b);
         } else
              Voicemail(${EXTEN}|u);
    };
    _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!);
         };
    };
};


NOTE: The conditional expression in if() statements (the "${DIALSTATUS}" = "BUSY" above) is wrapped in $[ ] for evaluation.
NOTE: Neither the switch nor case values are wrapped in $[ ]; they can be constants, or ${var} type references only.
NOTE: Using 'pattern' instead of 'case' permits usage of Asterisk Dialplan Patterns.
NOTE: AEL generates each case as a separate extension. case clauses with no terminating 'break', or 'goto', have a goto inserted, to the next clause, which creates a 'fall thru' effect.
NOTE: Since switches are implemented as extensions, ${EXTEN} will not work as desired.


goto and labels

This is an example of how to do a goto in AEL.


context gotoexample {
    s => {
begin:
         NoOp(Infinite Loop!  yay!);
         Wait(1);
         goto begin;    // go to label in same extension
    };
    3 => {
            goto s|begin;   // go to label in different extension
     };
     4 => {
            goto gotoexample|s|begin;  // overkill go to label in same context
     };
};

context gotoexample2 {
     s =>  {
   end: 
           goto gotoexample|s|begin;   // go to label in different context
     };
};


NOTE: goto labels follow the same requirements as the Goto() application, except the last value has to be a label. If the label does not exist, you will have run-time errors. If the label exists, but in a different extension, you have to specify both the extension name and label in the goto, as in: goto s|z; if the label is in a different context, you specify context|extension|label. There is a note about using goto's in a switch statement below...

Jumps

To call another extension (or, in a switch statement, another case), use the 'jump' statement:

context incoming {
   s => { 
        NoOp(Handle the call here); 
   };
   18665551212 => jump s; // we accept POTS calls at this number
};

context home {
   399 => jump s@incoming; // 399 is my 'simulate incoming call' speeddial ;)
};


Macros

A macro is defined in its own block like this. The arguments to the macro are specified with the name of the macro. They are then reffered to by that same name. A catch block can be specified to catch special extensions.


macro std-exten( ext , dev ) {
       Dial(${dev}/${ext},20);
       switch(${DIALSTATUS) {
       case BUSY:
               Voicemail(b${ext});
               break;
       default:
               Voicemail(u${ext});

       };
       catch a {
               VoiceMailMain(${ext});
               return;
       };
};


A macro is then called by preceeding the macro name with an ampersand.


context example {
    _5XXX => &std-exten(${EXTEN}, "IAX2");
};




Examples



context demo {
    s => {
         Wait(1);
         Answer();
         TIMEOUT(digit)=5;
         TIMEOUT(response)=10;
restart:
         Background(demo-congrats);
instructions:
         for (x=0; ${x} < 3; x=${x} + 1) {
              Background(demo-instruct);
              WaitExten();
         };
    };
    2 => {
         Background(demo-moreinfo);
         goto s|instructions;
    };
    3 => {
         LANGUAGE()=fr;
         goto s|restart;
    };
    500 => {
         Playback(demo-abouttotry);
         Dial(IAX2/guest@misery.digium.com);
         Playback(demo-nogo);
         goto s|instructions;
    };
    600 => {
         Playback(demo-echotest);
         Echo();
         Playback(demo-echodone);
         goto s|instructions;
    };
    # => {
hangup:
         Playback(demo-thanks);
         Hangup();
    };
    t => goto #|hangup;
    i => Playback(invalid);
};



Hints and Bugs

Note: These hints/bugs are as of asterisk 1.2.1, it's possible some of these limitations will be removed in the future

  • Every closing bracket '}', must be terminated with a semi-colon ';', including if-statments, contexts, macros, switch statements, extensions, etc. If you do not, any statements between the closing bracket and the next found semi-colon will be ignored, and not generate a warning, can be hard to debug.

  • You may _not_ have an empty case statement. Even if falling-thru to another, put a NoOp() in-between, or a very-hard-to-debug error will occur.

  • Never use a colon ':' unless constructing a label, parser does not check to see if colon is contained within quotes, or within a function call (even one such as NoOp, if you're just trying to print debugging). To use a colon as required for MACRO-EXIT and dial options, you can set a global variable to a colon ':' in extensions.conf, and call the variable as needed in your AEL scripts. This is a rough hack, but it does allow these features to function properly.

  • When using labels, never put one at the very end of a macro or extension in a context, always make sure at least one command (such as a NoOp) still exists after a label, otherwise the label will not be added to the dialplan. (It is often convenient to have a label at the end in order to issue a goto command to handle error conditions).

  • When in a switch statement, you cannot simply issue a goto for a label within the same context/extension/macro because the switch statment creates a new extension in the current context for each case statement, you must specify the full location of the label in the current context, like "goto s|mylabel" instead of "goto mylabel" , or avoid goto statements within switch statements.

  • When calling a 'FastAGI' you must escape the backslashes, for example: AGI(agi:\/\/127.0.0.1\/...).

Examples

Here you can find some examples on how to use AEL to create powerful dialplans: AEL Example Snippets.


AEL2 | AEL Example Snippets | Configuration | The Dialplan - extensions.conf | Dialplan Commands
Page Hits: 62877 ------------------------ Page Created: Wed 07 of Sep, 2005 18:56 UTC
Created by X1Z, Last modification by twisted on Tue 08 of May, 2007 [18:02 UTC]

Comments Filter

include other files?

by Johannes Zweng on Monday 16 of July, 2007 [07:15:46 UTC]
How can I include other files?
The "#include" directive seems not to work like in other config files (pbx_ael.c:1120 handle_root_token: Unknown root token '#include').

I am using Asterisk version 1.2.9.1.


EDIT:
2007/07/16:
Ok, I figured out, it works with Asterisk 1.4.5.


AEL Syntax Highlighting for VIM

by C. Chad Wallace on Thursday 17 of May, 2007 [17:14:21 UTC]
I've created a syntax file for VIM to highlight AEL. It can be found here:

http://www.vim.org/scripts/script.php?script_id=1900

Any comments or contributions are more than welcome!

goto

by Remco Post on Sunday 22 of October, 2006 [01:03:38 UTC]
goto not only takes labels as it's last argument, but also priorities, like: 'goto othercontext|${EXTEN}|1;', of course, in AEL, using priority numbers other than 1 is potentially dangerous.

Aw: Dialplan Errors

by cibi on Monday 07 of August, 2006 [22:41:04 UTC]
>Does anyone know how to deal with "errors" (ie n+101 priorities) in AEL?
Just look at the above samples. You use the DIALSTATUS variable for that.
You can even use it in the extension.conf (Asterisk 1.2.x) - priority jumping can be disabled in 1.2.x for the extensions.conf

I recommend everyone to take a look at AEL2.

Dialplan Errors

by Dr^Mouse on Tuesday 06 of June, 2006 [13:06:05 UTC]
Does anyone know how to deal with "errors" (ie n+101 priorities) in AEL?

For example, choosing whether to play the busy or unavailable voicemail message?

Switch requires default+break?

by cibi on Monday 02 of January, 2006 [14:06:12 UTC]
I'm using Asterisk 1.2.1-BRIstuffed-0.3.0-PRE-1d.
I use a code similar to this (Edit: the code is used in a macro)

switch(${ton}) {
       case 1:
           clipno=1;
           break;
       case 2:
           clipno=2;
           break;
   };
   NoOp(After the switch statement);

With ton=1 or ton=2, the NoOP (or any other code after that) is executed, but if ton is 0, it isn't. If add a default case with 1 NoOp, same result.
But if i add a default case (include some code, or just NoOP) + a closing break it works.

Comments in AEL

by Nik Middleton on Saturday 10 of December, 2005 [23:35:45 UTC]
I like to coment my dial plans, it would appear that the generic // seems to work

How to 'include' realtime extensions?

by Jan Van Nieuwenhove on Tuesday 06 of December, 2005 [23:16:06 UTC]
when using non-ael extensions, you can 'include' those neat realtime extensions like so:

switch => Realtime/mycontext@realtime_ext
; switch => Realtime/context@family/options
; If context is not given, current context is default
; If family is not given, family of 'extensions' is default

I assume this doesn't work in ael, as the keyword 'switch' means something else (a C-like meaning), does anyone know how I can do this?
It is probably like;
includes { something; };

If someone could shed some light on that 'something', I would be greatly obliged ;p

Re: restart required to reload?

by chapman_164 on Sunday 20 of November, 2005 [18:45:40 UTC]
Try "ael reload". It works as of 1.2.0-beta2

by greyhound on Saturday 19 of November, 2005 [04:13:34 UTC]
Digium bug system (http://bugs.digium.com/view.php?id=5744) says this is fixed in RC2. Haven't tested it, but just wanted to keep the notes here current.

Please update this page with new information, just login and click on the "Edit" or "Add Comment" button above. Get a free login here: Register Thanks! - support@voip-info.org

Page Changes | Comments

Sponsored by:

Terms of Service Privacy Policy
© 2003-2007 Arte Marketing, Inc.

Powered by bitweaver