mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-26 06:26:41 +00:00 
			
		
		
		
	git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5978 65c4cc65-6c06-0410-ace0-fbb531ad65f3
		
			
				
	
	
		
			266 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
| 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> reload pbx_ael.so
 | |
| 
 | |
| 
 | |
| Contexts
 | |
| -------------------------
 | |
| Contexts in AEL represent a set of extensions in the same way that they do
 | |
| in extensions.conf.
 | |
| 
 | |
| context default {
 | |
| 
 | |
| };
 | |
| 
 | |
| 
 | |
| 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;
 | |
| };
 | |
| 
 | |
| 
 | |
| 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;
 | |
| };
 | |
| 
 | |
| Variables can be set within extensions as well.
 | |
| 
 | |
| context foo {
 | |
| 	555 => {
 | |
| 		x=5;
 | |
| 		y=blah;
 | |
| 		NoOp(x is ${x} and y is ${y} !);
 | |
| 	};
 | |
| };
 | |
| 
 | |
| 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;
 | |
| 		};
 | |
| 	};
 | |
| };
 | |
| 
 | |
| 
 | |
| 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}) {
 | |
| 			case 7771:
 | |
| 				NoOp(You called 7771!);
 | |
| 				break;
 | |
| 			case 7772:
 | |
| 				NoOp(You called 7772!);
 | |
| 				break;
 | |
| 			case 7773:
 | |
| 				NoOp(You called 7773!);
 | |
| 				// fall through
 | |
| 			default:
 | |
| 				NoOp(In the default clause!);
 | |
| 		};
 | |
| 	};
 | |
| };
 | |
| 
 | |
| 
 | |
| 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;
 | |
| 	};
 | |
| };
 | |
| 
 | |
| 
 | |
| 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);
 | |
| };
 | |
| 
 |