{"id":34,"date":"2016-05-06T08:51:35","date_gmt":"2016-05-06T08:51:35","guid":{"rendered":"http:\/\/symbioticindia.in\/docu\/?p=34"},"modified":"2016-05-06T08:51:35","modified_gmt":"2016-05-06T08:51:35","slug":"a-simple-agi-scripting-engine-with-asterisk-java","status":"publish","type":"post","link":"http:\/\/symbioticindia.in\/docu\/2016\/05\/06\/a-simple-agi-scripting-engine-with-asterisk-java\/","title":{"rendered":"A simple AGI scripting engine with Asterisk-Java"},"content":{"rendered":"<div align=\"center\"><strong>ntroduction<\/strong><\/div>\n<div align=\"left\"><a title=\"Asterisk,\" href=\"http:\/\/www.asterisk.org\/\" target=\"_blank\">Asterisk,<\/a> the well known free PBX, exposes great integration potentialities. Specifically , we&#8217;re interested in AGI (Asterisk Gateway Interface), a sort of API for scripting the engine.<\/div>\n<div align=\"left\">Today we&#8217;ll face a java interface for AGI: <a title=\"asterisk-java.\" href=\"http:\/\/asterisk-java.org\/\" target=\"_blank\">asterisk-java.<\/a> We&#8217;ll use this easy library to build a scripting engine. The used scripting language is <a title=\"BeanShell\" href=\"http:\/\/www.beanshell.org\/\" target=\"_blank\">BeanShell<\/a>, but you can virtually use any language supported by the Sun jdk (python,ruby,groovy, javascript etc.).<\/div>\n<div>\n<div>\n<div>\n<h4>Asterisk-Java and AGI &#8211; some code<\/h4>\n<\/div>\n<p>The library asterisk-java is of immediate use; its simplest use is based on fastagi protocol, and though it also exposes a Manager API, fastagi will be enough for this article purposes . To build our scripting engine we just need to subclass &#8220;BaseAgiScript&#8221; and\u00a0 override its &#8220;service&#8221; method. From the AgiRequest object we&#8217;ll grab the parameter we&#8217;re interested in, &#8220;script&#8221;, which is just the name of a beanshell script we want to execute. We&#8217;ll then pass a reference of our class, the AgiRequest and the AgiChannel object to the beanshell interpreter, launch a global script that defines some utility functions (see below) and finally launch the requested script. The approach is quite flexible, our script engine doesn&#8217;t need to be on the same computer the pbx is on, and we can add\/modify our scripts on the fly without need for compilation or engine restart.<\/p>\n<div><\/div>\n<\/div>\n<\/div>\n<pre><span style=\"color: #f5deb3;\"><span style=\"color: #00cc99;\">package<\/span> org.beanizer.bagiserver;\r\n\r\n\r\n<span style=\"color: #00cc99;\">import<\/span> bsh.EvalError;\r\n<span style=\"color: #00cc99;\">import<\/span> java.io.FileNotFoundException;\r\n<span style=\"color: #00cc99;\">import<\/span> java.io.IOException;\r\n<span style=\"color: #00cc99;\">import<\/span> org.asteriskjava.fastagi.AgiChannel;\r\n<span style=\"color: #00cc99;\">import<\/span> org.asteriskjava.fastagi.AgiException;\r\n<span style=\"color: #00cc99;\">import<\/span> org.asteriskjava.fastagi.AgiRequest;\r\n<span style=\"color: #00cc99;\">import<\/span> org.asteriskjava.fastagi.BaseAgiScript;\r\n\r\n<span style=\"color: #00cc99;\">import<\/span> bsh.Interpreter;\r\n\r\n<span style=\"color: #ffa500;\">public<\/span> <span style=\"color: #cc6600;\">class<\/span> BAgiServer <span style=\"color: #ffa500;\">extends<\/span> BaseAgiScript<span style=\"color: #00ffff;\">{<\/span>\r\n    \r\n    <span style=\"color: #ffa500;\">public<\/span> <span style=\"color: #b2dfee;\">BAgiServer<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">{<\/span>\r\n    <span style=\"color: #00ffff;\">}<\/span>\r\n\r\n    <span style=\"color: #ffa500;\">public<\/span> <span style=\"color: #cc6600;\">void<\/span> <span style=\"color: #b2dfee;\">service<\/span><span style=\"color: #00ffff;\">(<\/span>AgiRequest request, AgiChannel channel<span style=\"color: #00ffff;\">)<\/span>\r\n    <span style=\"color: #ffa500;\">throws<\/span> AgiException <span style=\"color: #00ffff;\">{<\/span>\r\n        \r\n        Interpreter interp<span style=\"color: #00ffff;\">=<\/span><span style=\"color: #ffa500;\">new<\/span> <span style=\"color: #b2dfee;\">Interpreter<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n        <span style=\"color: #ffa500;\">try<\/span> <span style=\"color: #00ffff;\">{<\/span>\r\n            String script<span style=\"color: #00ffff;\">=<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">(<\/span>request.<span style=\"color: #b2dfee;\">getParameter<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">script<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">!<\/span><span style=\"color: #00ffff;\">=<\/span><span style=\"color: #ffff66;\">null<\/span><span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">&amp;<\/span><span style=\"color: #00ffff;\">&amp;<\/span> <span style=\"color: #00ffff;\">!<\/span><span style=\"color: #00ffff;\">(<\/span> request.<span style=\"color: #b2dfee;\">getParameter<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">script<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span>.<span style=\"color: #b2dfee;\">equals<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">)<\/span><\/span><\/pre>\n<pre>\t\t\t\t\t\t\t\t<span style=\"color: #f5deb3;\">? request.<span style=\"color: #b2dfee;\">getParameter<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">script<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span> : <span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">..\/scriptlib\/default<\/span><span style=\"color: #00cd00;\">\"<\/span>;\r\n            interp.<span style=\"color: #b2dfee;\">source<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">scriptlib\/bagi_import.bsh<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n            interp.<span style=\"color: #b2dfee;\">set<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">bagi<\/span><span style=\"color: #00cd00;\">\"<\/span>,<span style=\"color: #ffff66;\">this<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n            interp.<span style=\"color: #b2dfee;\">set<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">request<\/span><span style=\"color: #00cd00;\">\"<\/span>,request<span style=\"color: #00ffff;\">)<\/span>;\r\n            interp.<span style=\"color: #b2dfee;\">set<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">channel<\/span><span style=\"color: #00cd00;\">\"<\/span>,channel<span style=\"color: #00ffff;\">)<\/span>;\r\n            \r\n            interp.<span style=\"color: #b2dfee;\">source<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">scripts\/<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">+<\/span> script <span style=\"color: #00ffff;\">+<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">.bsh<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n            \r\n        <span style=\"color: #00ffff;\">}<\/span> <span style=\"color: #ffa500;\">catch<\/span> <span style=\"color: #00ffff;\">(<\/span>FileNotFoundException ex<span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">{<\/span>\r\n            ex.<span style=\"color: #b2dfee;\">printStackTrace<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n        <span style=\"color: #00ffff;\">}<\/span> <span style=\"color: #ffa500;\">catch<\/span> <span style=\"color: #00ffff;\">(<\/span>IOException ex<span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">{<\/span>\r\n            ex.<span style=\"color: #b2dfee;\">printStackTrace<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n        <span style=\"color: #00ffff;\">}<\/span> <span style=\"color: #ffa500;\">catch<\/span> <span style=\"color: #00ffff;\">(<\/span>EvalError ex<span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">{<\/span>\r\n            ex.<span style=\"color: #b2dfee;\">printStackTrace<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n        <span style=\"color: #00ffff;\">}<\/span>\r\n    <span style=\"color: #00ffff;\">}<\/span>\r\n   \r\n<span style=\"color: #00ffff;\">}<\/span> <\/span><\/pre>\n<p>A &#8220;fastagi-mapping.properties&#8221; file must exists on the classpath of the scripting engine and should contain something like this:<\/p>\n<pre>server.agi = BAgiServer\r\n\r\n<\/pre>\n<p>where &#8220;server.agi&#8221; is the agi script name called from asterisk, to be mapped to &#8220;BagiServer&#8221;, our class name.<\/p>\n<p>We also need to add a call to our engine from asterisk&#8217;s dialplan, so in &#8220;extensions.conf&#8221; we&#8217;ll add something like:<\/p>\n<pre>\r\nexten =&gt; 1200,1,Agi(agi:\/\/localhost\/server.agi?script=scriptname)\r\n\r\n<\/pre>\n<p>where &#8220;1200&#8221; can be an extension number of your choice, &#8220;localhost&#8221; is the server your scripting engine is hosted on, &#8220;server.agi&#8221; is the name we&#8217;ve mapped for our scripting engine and &#8220;scriptname&#8221; is the name of the beanshell script we want to invoke(without .bsh extension).<\/p>\n<p>When someone will try to call extension &#8220;1200&#8221;, the specified agi script will be executed.<\/p>\n<p>In our source code you can see we&#8217;re using two directories relative to the base classpath of BAgiServer:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>&#8220;scriptlib&#8221;, wich contains scripts &#8220;default&#8221;(called if no script name is passed as parameter), and &#8220;bagi_import&#8221; ( where we put generic functions we can use from other scripts).<\/li>\n<li>&#8220;scripts&#8221; , containing all the user defined scripts.<\/li>\n<\/ul>\n<p>Obviously these paths are arbitrary and you can choose differently. Now let&#8217;s have a look at our beanshell scripts.<\/p>\n<div>\n<div>bagi_import.bsh<\/div>\n<div>\nThis is an utility script automatically included each time the engine gets called, so we should put here all the general purpose functions. Here is how it is now:<\/p>\n<\/div>\n<\/div>\n<pre><\/pre>\n<pre><span style=\"color: #f5deb3;\"><span style=\"color: #00cc99;\">\r\nimport<\/span> org.asteriskjava.fastagi.AgiChannel;\r\n<span style=\"color: #00cc99;\">import<\/span> org.asteriskjava.fastagi.AgiException;\r\n<span style=\"color: #00cc99;\">import<\/span> org.asteriskjava.fastagi.AgiRequest;\r\n<span style=\"color: #00cc99;\">import<\/span> org.asteriskjava.fastagi.BaseAgiScript;\r\n\r\n<span style=\"color: #00cc99;\">import<\/span> org.beanizer.bagiserver.BAgiServer;\r\n\r\nBAgiServer bagi;\r\nAgiRequest request;\r\nAgiChannel channel;\r\n\r\n<span style=\"color: #b2dfee;\">say<\/span><span style=\"color: #00ffff;\">(<\/span>String string<span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">{<\/span>\r\n    java.rmi.server.UID uid<span style=\"color: #00ffff;\">=<\/span><span style=\"color: #ffa500;\">new<\/span> java.rmi.server.<span style=\"color: #b2dfee;\">UID<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n    String command<span style=\"color: #00ffff;\">=<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">echo<\/span> <span style=\"color: #00cd00;\">'<\/span><span style=\"color: #00cd00;\">\"<\/span> <span style=\"color: #00ffff;\">+<\/span> string <span style=\"color: #00ffff;\">+<\/span> <span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">'<\/span> <span style=\"color: #00cd00;\">|<\/span> <span style=\"color: #00cd00;\">text2wave<\/span> <span style=\"color: #00cd00;\">-scale<\/span> <span style=\"color: #00cd00;\">8<\/span> <span style=\"color: #00cd00;\">-o<\/span> <span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">+<\/span> <span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">\/tmp\/<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">+<\/span>uid.<span style=\"color: #b2dfee;\">toString<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">+<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">.ulaw<\/span> <span style=\"color: #00cd00;\">-otype<\/span> <span style=\"color: #00cd00;\">ulaw<\/span> <span style=\"color: #00cd00;\">-<\/span><span style=\"color: #00cd00;\">\"<\/span>;     \r\n    channel.<span style=\"color: #b2dfee;\">exec<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">System<\/span><span style=\"color: #00cd00;\">\"<\/span>,command <span style=\"color: #00ffff;\">)<\/span>;\r\n    channel.<span style=\"color: #b2dfee;\">streamFile<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">\/tmp\/<\/span><span style=\"color: #00cd00;\">\"<\/span> <span style=\"color: #00ffff;\">+<\/span>uid.<span style=\"color: #b2dfee;\">toString<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n    channel.<span style=\"color: #b2dfee;\">exec<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">System<\/span><span style=\"color: #00cd00;\">\"<\/span>,<span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">rm<\/span> <span style=\"color: #00cd00;\">\/tmp\/<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">+<\/span> uid.<span style=\"color: #b2dfee;\">toString<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">+<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">.ulaw<\/span><span style=\"color: #00cd00;\">\"<\/span> <span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #00ffff;\">}<\/span>\r\n<span style=\"color: #b2dfee;\">answer<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">{<\/span>\r\n    channel.<span style=\"color: #b2dfee;\">answer<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #00ffff;\">}<\/span>\r\n<span style=\"color: #b2dfee;\">hangup<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">{<\/span>\r\n    channel.<span style=\"color: #b2dfee;\">hangup<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #00ffff;\">}<\/span>\r\n<span style=\"color: #b2dfee;\">getDigits<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #cc6600;\">int<\/span> number<span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">{<\/span>\r\n    StringBuffer sb<span style=\"color: #00ffff;\">=<\/span><span style=\"color: #ffa500;\">new<\/span> <span style=\"color: #b2dfee;\">StringBuffer<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n    <span style=\"color: #ffa500;\">for<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #cc6600;\">int<\/span> t<span style=\"color: #00ffff;\">=<\/span><span style=\"color: #cdcd00;\">0<\/span>;t<span style=\"color: #00ffff;\">&lt;<\/span>number;t<span style=\"color: #00ffff;\">+<\/span><span style=\"color: #00ffff;\">+<\/span><span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">{<\/span>\r\n        sb.<span style=\"color: #b2dfee;\">append<\/span><span style=\"color: #00ffff;\">(<\/span>channel.<span style=\"color: #b2dfee;\">waitForDigit<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #cdcd00;\">10000<\/span><span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n    <span style=\"color: #00ffff;\">}<\/span>\r\n    <span style=\"color: #ffa500;\">return<\/span> sb.<span style=\"color: #b2dfee;\">toString<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #00ffff;\">}<\/span>\r\n\r\n<span style=\"color: #b2dfee;\">wait<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #cc6600;\">int<\/span> millis<span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">{<\/span>\r\n    <span style=\"color: #00ffff;\">(<\/span><span style=\"color: #ffa500;\">new<\/span> <span style=\"color: #b2dfee;\">Thread<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span><span style=\"color: #00ffff;\">)<\/span>.<span style=\"color: #b2dfee;\">sleep<\/span><span style=\"color: #00ffff;\">(<\/span>millis<span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #00ffff;\">}<\/span> <\/span><\/pre>\n<p>Here we basically import some useful classes, instantiate BAgiServer,AgiRequest and AgiChannel, and then define some functions. These just do what their names say, note how most of the time we just wrap AgiChannel&#8217;s methods (&#8220;answer&#8221; and &#8220;hangup&#8221; i.e.).<\/p>\n<p>&#8220;getDigits&#8221;, makes use of the method &#8220;waitForDigit&#8221; of AgiChannel to wait for the user to input a number of digits specified by the function parameter and returns the entire number as a string.<\/p>\n<p>&#8220;say&#8221;, is used to achieve text-to-speech. Instead of using festival or flite, here we use a lighter approach. Using the &#8220;exec&#8221; method of AgiChannel we launch &#8220;text2wave&#8221; on the pbx host (so text2wave must be installed there), and save the resulting sound file in a tmp directory with a random name.<\/p>\n<p>We then use &#8220;streamFile&#8221; to stream the sound to the user and finally delete the sound file from the tmp directory.<\/p>\n<pre><\/pre>\n<div>\n<div>default.bsh<\/div>\n<div>This is called when no script to be executed has been specified.<\/p>\n<pre><span style=\"color: #f5deb3;\"><span style=\"color: #b2dfee;\">\r\nanswer<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #b2dfee;\">wait<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #cdcd00;\">1000<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #b2dfee;\">say<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">No<\/span> <span style=\"color: #00cd00;\">script<\/span> <span style=\"color: #00cd00;\">defined<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #b2dfee;\">wait<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #cdcd00;\">1000<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #b2dfee;\">hangup<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<\/span><span style=\"color: #f5deb3;\">\r\n<\/span><\/pre>\n<div>\n<\/div>\n<div>As you can see, it makes use of the functions defined in bagi_import.bsh.\u00a0 It answers the call, waits for a second, says a phrase, waits another second and then hangs up.<\/p>\n<\/div>\n<div>\n<div>test.bsh<\/div>\n<div>And now an example of a user defined script. This script must reside in the &#8220;scripts&#8221; directory, and the agi call from asterisk should be something like this:<\/p>\n<pre>exten =&gt; 1200,1,Agi(agi:\/\/localhost\/server.agi?script=test)<\/pre>\n<p>And here is the code:<\/p><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<pre><span style=\"color: #f5deb3;\"><span style=\"color: #b2dfee;\">\r\n<\/span><\/span><span style=\"color: #f5deb3;\"><span style=\"color: #00cc99;\">import<\/span> org.asteriskjava.fastagi.command.*;\r\n<span style=\"color: #b2dfee;\">answer<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #b2dfee;\">wait<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #cdcd00;\">1000<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #b2dfee;\">say<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">Please,<\/span> <span style=\"color: #00cd00;\">enter<\/span> <span style=\"color: #00cd00;\">extension<\/span> <span style=\"color: #00cd00;\">code<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\nString code <span style=\"color: #00ffff;\">=<\/span> <span style=\"color: #b2dfee;\">getDigits<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #cdcd00;\">3<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #b2dfee;\">say<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">Trying<\/span> <span style=\"color: #00cd00;\">to<\/span> <span style=\"color: #00cd00;\">call<\/span> <span style=\"color: #00cd00;\">extension:<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\nchannel.<span style=\"color: #b2dfee;\">sayDigits<\/span><span style=\"color: #00ffff;\">(<\/span>code<span style=\"color: #00ffff;\">)<\/span>;\r\nchannel.<span style=\"color: #b2dfee;\">exec<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">ChannelRedirect<\/span><span style=\"color: #00cd00;\">\"<\/span>, channel.<span style=\"color: #b2dfee;\">getName<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span> <span style=\"color: #00ffff;\">+<\/span> <span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">|from-internal|<\/span><span style=\"color: #00cd00;\">\"<\/span> <span style=\"color: #00ffff;\">+<\/span> code <span style=\"color: #00ffff;\">+<\/span> <span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00cd00;\">|1<\/span><span style=\"color: #00cd00;\">\"<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<span style=\"color: #b2dfee;\">hangup<\/span><span style=\"color: #00ffff;\">(<\/span><span style=\"color: #00ffff;\">)<\/span>;\r\n<\/span><\/pre>\n<p>I&#8217;m sure you can appreciate how easy it is now to write a script. In this case the script answers and waits for a while, then asks for an extension number to be dialed, reads aloud the dialed code and then tries to redirect the call to the requested extension, using th &#8220;ChannelRedirect&#8221; asterisk command. Then it hangs up.<\/p>\n<p>If you want to test this approach, here are a couple of guidelines:<\/p>\n<ul>\n<li>The directory structure\u00a0 should be like this:<\/li>\n<\/ul>\n<p>basedir<br \/>\nscriptlib<br \/>\nbagi_import.bsh<br \/>\ndefault.bsh<br \/>\nscripts<br \/>\nyour_scripts_go_here.bsh<br \/>\nlib<br \/>\nasteriskjava.jar\u00a0 (the name depends on the version)<br \/>\nbeanshell.jar\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (the name depends on the version)<br \/>\nbagiserver.jar\u00a0\u00a0\u00a0\u00a0 (it&#8217;s just org.beanizer.bagiserver.BAgiServer.class jarred)<br \/>\nfastagi-mapping.properties<\/p>\n<ul>\n<li>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 from &#8220;basedir&#8221;, start the\u00a0 engine including in your classpath the &#8220;lib&#8221; dir and all the jars it contains, and launching the class org.asteriskjava.fastagi.DefaultAgiServer<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<div>\n<div>Conclusions<\/div>\n<div>\nThe proposed is just a skeleton of what could grow as a more complete agi scripting engine for java (or even ruby,python,javascript,groovy) developers involved in integrating asterisk with other platforms.<br \/>\nIt&#8217;s quite easy to extend the engine by adding methods in the java class or, better, by adding functions to bagi_import.bsh<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>ntroduction Asterisk, the well known free PBX, exposes great integration potentialities. Specifically , we&#8217;re interested in AGI (Asterisk Gateway Interface), a sort of API for scripting the engine. Today we&#8217;ll face a java interface for AGI: asterisk-java. We&#8217;ll use this easy library to build a scripting engine. The used scripting language is BeanShell, but you ..<\/p>\n<div class=\"clear-fix\"><\/div>\n<p><a href=\"http:\/\/symbioticindia.in\/docu\/2016\/05\/06\/a-simple-agi-scripting-engine-with-asterisk-java\/\" title=\"read more...\">Read more<\/a><\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,5],"tags":[],"class_list":["post-34","post","type-post","status-publish","format-standard","hentry","category-asterisk","category-java"],"_links":{"self":[{"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/posts\/34","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/comments?post=34"}],"version-history":[{"count":1,"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/posts\/34\/revisions"}],"predecessor-version":[{"id":35,"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/posts\/34\/revisions\/35"}],"wp:attachment":[{"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/media?parent=34"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/categories?post=34"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/symbioticindia.in\/docu\/wp-json\/wp\/v2\/tags?post=34"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}