Mod lua

From FreeSWITCH Wiki

(Redirected from Lua)
Jump to: navigation, search

Contents

Features

Write IVR scripts in Lua

It has a very easy to use syntax, see the Hello Lua script.

Serve configs (the same way mod_xml_curl does it)

Examples

Make API calls directly from Lua code

Examples

Lightweight

Stripped mod_lua.so is 272k

Highly Embeddable

As far as embeddability goes - python ranks a 2, perl ranks a 4, js is a 5, and lua is a 10!

luarun at the CLI

You can issue a "luarun /path/to/script.lua" and launch a thread which your lua script will run in. The "lua" command is for inline lua like from the dialplan ie ${lua(codehere)}. "luarun" will spawn a thread while "lua" will block till the code is complete.

Passing Arguments

Arguments are passed as space-separated values:

luarun arg1 arg2 arg3

Arguments are accessed with "argv" like this:

my_first_var = argv[1];
my_next_var = argv[2];

And so on...

Configuring

For IVR use

Nothing should be needed here.

For making API calls

api = freeswitch.API();
digits = api:execute("regex", "testing1234|/(\\d+)/|$1");
-- The returned output of the API call is stored in the variable if you need it.
freeswitch.consoleLog("info", "Extracted digits: " .. digits .. "\n")

To call another Lua script

api = freeswitch.API();
reply = api:executeString("luarun another.lua");

For serving configuration

For serving configuration with mod_lua:

  • You can bind a script to the XML req, like you do with URL in mod_xml_curl.
  • When something looks up sections in the XML registry, it calls your script.
  • Your script does any db lookups or whatever it needs, and it returns the XML string.
  • Note: When you edit lua.conf.xml, giving the reloadxml command from the FreeSWITCH console is not sufficient to recognize the "xml-handler-script" parameters. You have to restart FreeSWITCH.
  • Some examples for the "xml-handler-bindings" parameter: "dialplan" "directory" "dialplan|directory"

The file conf/autoload_configs/lua.conf.xml is used in the default FreeSWITCH™ setup.

Here is a minimum configuration file, it will fetch a dialplan from Lua script.

<configuration name="lua.conf" description="LUA Configuration">
  <settings>
    <param name="xml-handler-script" value="dp.lua"/>
    <param name="xml-handler-bindings" value="dialplan"/>
  </settings>
</configuration>


This is a sample dp.lua, whatever is in XML_STRING will be returned to freeswitch once the script is finished.

-- params is the event passed into us we can use params:getHeader to grab things we want.
io.write("TEST\n" .. params:serialize("xml") .. "\n");  

mydialplan = [[
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="freeswitch/xml">
  <section name="dialplan" description="RE Dial Plan For FreeSwitch">
    <context name="default">
      <extension name="freeswitch_public_conf_via_sip">
        <condition field="destination_number" expression="^9(888|1616)$">
          <action application="bridge" data="sofia/${use_profile}/$1@conference.freeswitch.org"/>
        </condition>
      </extension>
    </context>
  </section>
</document>
]]

XML_STRING = mydialplan

For dialplan

In for example a sip profile you can - instead of XML dialplan - use LUA directly to generate a dialplan:

<profile name="phones">
  <!-- ... -->
  <settings>
    <param name="dialplan" value="LUA"/>
    <param name="context" value="dialplan-from-phones.lua"/>
    <!-- ... -->
  </settings>
</profile>

Then create a dialplan in scripts/dialplan-from-phones.lua like this:

-- dialplan-from-phones.lua

ACTIONS = {}

freeswitch.consoleLog("notice", "from your script")

table.insert(ACTIONS, "answer")
table.insert(ACTIONS, {"log", "NOTICE after your script"})

The entire table (array) of actions will be executed after the LUA script has stopped.

This works the same as when the XML dialplan generates a list of actions that is run after it has reached the end.

Note that you must not use media directly from your script (eg session:answer()) like you could if it were called as an IVR script.

Advantage of this method over answering from an IVR script is that during the call itself there will be no LUA script (per session) running - which could add up if you have a few thousand sessions going.

Alternative is to call a LUA script from the XML dialplan that only sets some channel variables that will be picked up by consecutive applications - or you can generate an XML stub as is described in the previous section.

Of course it is also possible to transfer from one dialplan to another.

From LUA to XML:

table.insert(ACTIONS, {"transfer", "123 XML some-context"})

From XML to LUA:

<action application="transfer" data="123 LUA some-dialplan.lua"/>

Lua scripts at startup

Here is a minimum configuration file:

<configuration name="lua.conf" description="LUA Configuration">
  <settings>
    <!--
	The following options identifies a lua script that is launched
	at startup and may live forever in the background.
	You can define multiple lines, one for each script you 
	need to run.
    -->
    <!--<param name="startup-script" value="startup_script_1.lua"/>-->
    <!--<param name="startup-script" value="startup_script_2.lua"/>-->
  </settings>
</configuration>


The start-up script values represent lua scripts (located inside the scripts/ directory) that are launched when FreeSWITCH is started. The scripts live in their own thread. You can use them to run simple tasks (and then let them finish) or looping forever, watching (for example) for events, generating calls or whatever you like.

Sample Dialplan

<action application="lua" data="helloworld.lua arg1 arg2"/> 

NOTE: arguments can be accessed by using argv[1] argv[2] in your script
NOTE: for looking up the location of the helloworld.lua file, it looks in prefix/scripts by default

Sample IVR's

Hello Lua

-- answer the call
session:answer();

-- sleep a second
session:sleep(1000);

-- play a file
session:streamFile("/path/to/blah.wav");

-- hangup
session:hangup();

LUA Regex Example

using this method, you can execute regex conditions from inside your lua scripts. ( thanks bkw_ )

session:execute("set", "some_chan_variable=${regex(" .. destination .. "|^([0-9]{10})$)}")

if destination is a lua variable.. with your destination number in it... and your regex was ^([0-9]{10})$ the result will be put in "some_chan_variable" that you can get thorough a session:getVariable

you can also do

session:execute("set", "some_chan_variable=${regex(" .. destination .. "|^(0|61)([2,3,7,8][0-9]{8})$|$2)}")

to match and return parts of your regex..

More Samples

FAQ

Where do I put 3rd part lua scripts/modules?

Q: Where do I need to stick my lua classes for FS to see them. I am running a lua script from within the /scripts folder, but it includes (requires) another lua file. FS.

A: (short answer) /usr/local/share/lua/5.1/

Alternatively, you can install a system lua (think apt-get or yum), and the lua embedded in freeswitch will look in the add-ons directory.

To do this in the mod_lua.conf file (currently not possible), the following development would be needed.

* Install them to a nonstandard.
* Push a nonstandard place into the path of where it looks.

NOTE: Assuming you have <param name="module-directory" value="$${base_dir}/scripts/?.so"/> in lua.conf.xml, in the scripts, require statements in the form of:

require "luasql.mysql"

This will look for the shared object ${base_dir}/scripts/luasql/mysql.so

NOTE: The native MySQL driver for Lua has a very bad memory leak. Do not use it.

How can I make it use the "system lua"

Q: I have lua installed, but mod_lua seems to ignore the LUA binary.

A: Lua is so small that the whole ball of wax is statically linked into the module!

How can I get LUA to see my own libraries using "require"

Q: Can I use the require mechanism for including libraries with the LUA in FreeSWITCH?

A: You will need to alter the LUA_PATH variable to instruct the embedded LUA inside FreeSWITCH to find your libraries. A simple startup script to do this is:

#!/bin/bash
export LUA_PATH=/usr/local/freeswitch/scripts/?.lua\;\;
ulimit -s 240
screen /usr/local/freeswitch/bin/freeswitch


Can I access a database via ODBC?

Yes, see luasql (LuaSQL 2.1.1)

WARNING: On x64_86 you need to change in config a few things

http://luaforge.net/frs/download.php/2686/luasql-2.1.1.tar.gz
tar xfvz luasql-2.1.1.tar.gz
cd luasql-2.1.1/


Example: to use Microsoft SQL Server:

sed -i 's/#T= odbc/T= odbc/g' config
sed -i 's/T=sqlite3/#T=sqlite3/g' config

DRIVER_LIBS= -L/usr/lib64 -lodbc
DRIVER_INCS= -DUNIXODBC -I/usr/include

Set proper values for LUA_LIBDIR, LUA_DIR , LUA_INC , DRIVER_LIBS, DRIVER_INCS

To allow compile properly:

sed -i 's/WARN= /WARN= -fPIC /g' config 

Compile.

make
make install

First you need to download and install Lua, and download LuaSQL, and compile and install whichever database modules you want to use. Next you can do something like:

#!/usr/local/bin/lua
require "luasql.mysql"

env = assert (luasql.mysql())
con = assert (env:connect("database","username","password","localhost"))
cur = assert (con:execute"SELECT * FROM table")
row = cur:fetch ({}, "a")

session:setVariable("varname", tostring(row.column));

cur:close()
con:close()
env:close()

NOTE:I found you also need to set some environment variables for scripts to run properly

echo export LUA_PATH=/usr/local/freeswitch/scripts/?.lua >> /etc/bashrc
echo export LUA_CPATH=/usr/local/freeswitch/scripts/?.so >> /etc/bashrc
echo export PATH=$PATH:/usr/local/freeswitch/bin >> ~/.bashrc

NOTE: you need to symlink the shared object (ie: mysql.so) to /usr/local/lib/lua/5.1/luasql/mysql.so

WARNING: This change breaks load of external lua modules http://fisheye.freeswitch.org:8081/changelog/FreeSWITCH?cs=9605

NOTE: Fixed http://fisheye.freeswitch.org:8081/changelog/FreeSWITCH?cs=10306

How can I find useful undocumented Session Functions?

There may be times when a function gets added, but not documented. This simple LUA script may help.

-- This function simply tells us what function are available in Session
--   It just prints a list of all functions.  We may be able to find functions
--   that have not yet been documented but are useful.  I did :)
function printSessionFunctions( session )

   metatbl = getmetatable(session)
   if not metatbl then return nil end

   local f=metatbl['.fn'] -- gets the functions table
   if not f then return nil end

   print("\n***Session Functions***\n")
   for k,v in pairs(f) do print(k,v) end
   print("\n\n")

end

new_session = freeswitch.Session() -- create a blank session

printSessionFunctions(new_session)


At freeswitch revision 16256 this is the output of the script:

process_callback_result function: 0x79b380
flushDigits     function: 0x798db0
execute function: 0x798ed0
setAutoHangup   function: 0x798de0
collectDigits   function: 0x798c30
mediaReady      function: 0x7993d0
speak   function: 0x79b2d0
setHangupHook   function: 0x799510
getDigits       function: 0x798c60
check_hangup_hook       function: 0x799380
playAndGetDigits        function: 0x798cf0
getState        function: 0x79b1e0
hangupState     function: 0x79b4e0
say     function: 0x79b150
recordFile      function: 0x79b210
waitForAnswer   function: 0x798ea0
sleep   function: 0x798d50
setEventData    function: 0x798f30
setPrivate      function: 0x79b540
setLUA  function: 0x7995d0
begin_allow_threads     function: 0x799320
setInputCallback        function: 0x7994e0
unsetInputCallback      function: 0x799470
run_dtmf_callback       function: 0x799400
get_cb_args     function: 0x799020
read    function: 0x798cc0
getPrivate      function: 0x79b570
answer  function: 0x79b450
setVariable     function: 0x79b510
getXMLCDR       function: 0x798f60
originate       function: 0x799570
destroy function: 0x7992f0
answered        function: 0x798e70
set_tts_parms   function: 0x79b300
sendEvent       function: 0x798f00
ready   function: 0x799540
preAnswer       function: 0x79b4b0
streamFile      function: 0x798d20
hangupCause     function: 0x79b1b0
setDTMFCallback function: 0x79b2a0
getVariable     function: 0x79b350
transfer        function: 0x798c90
get_uuid        function: 0x798ff0
hangup  function: 0x79b480
end_allow_threads       function: 0x799350
flushEvents     function: 0x798d80
sayPhrase       function: 0x79b180

API

Events

These methods apply to generating events.

event:addBody


--Create Custom event
				
custom_msg = 	"dial_record_id: " .. dial_record_id .. "\n" .. 
		"call_disposition: " .. Disposition .. "\n" ..
		"campaign_number: "  .. Campaign .. "\n" ..
		"called_number: "    .. dial_num .."\n"  ;  
		local e = freeswitch.Event("custom", "dial::dial-result");


		e:addBody(custom_msg);
		e:fire();

You can add as much data to the body as you like, in this case 4 items are to be sent.

The result will be

[Content-Length] => 555
    [Content-Type] => text/event-plain
    [Body] => Array
        (
            [Event-Subclass] => dial::dial-result
            [Event-Name] => CUSTOM
            [Core-UUID] => 2dc7cc50-b157-4868-ae16-04e5f4b95dae
            [FreeSWITCH-Hostname] => pp6.noble.co.uk
            [FreeSWITCH-IPv4] => 192.168.0.106
            [FreeSWITCH-IPv6] => ::1
            [Event-Date-Local] => 2009-02-17 23:15:49
            [Event-Date-GMT] => Tue, 17 Feb 2009 23:15:49 GMT
            [Event-Date-Timestamp] => 1234912549610060
            [Event-Calling-File] => switch_cpp.cpp
            [Event-Calling-Function] => fire
            [Event-Calling-Line-Number] => 297
            [Content-Length] => 85
            [Body] => Array
                (
                    [dial_record_id] => 1234
                    [call_disposition] => AA
                    [campaign_number] => 20
                    [called_number] => 7777777
                )

        )

)

event:addHeader

event:delHeader

event:fire

bkw gave the example of such...

local event = freeswitch.Event("message_waiting");
event:addHeader("MWI-Messages-Waiting", "no");
event:addHeader("MWI-Message-Account", "sip:1000@10.0.1.100");
event:addHeader("Sofia-Profile", "internal");
event:fire();

event:getBody

event:getHeader

This is a generic API call.

event:getHeader("Caller-Caller-ID-Name")

Or, This can be used inside of a dialplan.lua to get certain information

params:getHeader("variable_sip_req_uri")

event:getType

event:serialize

Use this to dump all available Headers to the console.

io.write(params:serialize());

Or this to display them as an info message.

freeswitch.consoleLog("info",params:serialize())

event:setPriority

Sending an Event

Using luarun to execute this code you can toggle the MWI on a registered phone on and off.

local event = freeswitch.Event("message_waiting");                                                                                                              
event:addHeader("MWI-Messages-Waiting", "no");                                                                                                                 
event:addHeader("MWI-Message-Account", "sip:1002@10.0.1.100");                                                                                                 
event:fire();  


Sessions

The following methods can be applied to existing sessions.

session:answer

Answer the session:

session:answer();

session:answered

session:bridged

Check to see if this session's channel is bridged to another channel.

if (session:bridged() == true) do
    -- Do something
end

session:check_hangup_hook

session:collectDigits

session:execute

session:execute(app, data)

local mySound = "/usr/local/freeswitch/sounds/music/16000/partita-no-3-in-e-major-bwv-1006-1-preludio.wav"

session:execute("playback", mySound)

Callbacks (DTMF and friends) CAN NOT EXECUTE during an execute.

session:flushDigits

session:flushEvents

session:get_uuid

session:getDigits

Get digits:

  • getDigits has three arguments: max_digits, terminators, timeout
  • max_digits: maximum number of DTMF tones that will be collected
  • terminators: buffer of characters that will terminate the digit collection
  • timeout: maximum time in milliseconds allowed for digit collection
  • return: buffer containing collected digits
  • The method blocks until one of the exit criteria is met.
digits = session:getDigits(5, "#", 3000);
freeswitch.consoleLog("info", "Got dtmf: ".. digits .."\n");

session:getState

Get the call state, i.e. "CS_EXECUTE". The call states are described in "switch_types.h".

state=session:getState();


session:getVariable

To get system variables such as ${hold_music}

local moh = session:getVariable("hold_music")
--[[ events obtained from "switch_channel.c"
 regards Monroy from Mexico
]]	
        session:getVariable("context");
	session:getVariable("destination_number");
	session:getVariable("caller_id_name");
	session:getVariable("caller_id_number");
	session:getVariable("network_addr");
	session:getVariable("ani");
	session:getVariable("aniii");
	session:getVariable("rdnis");
	session:getVariable("source");
	session:getVariable("chan_name");
	session:getVariable("uuid");

session:hangup

You can hang up a session and provide an optional Hangup causes.

session:hangup("USER_BUSY");

or 

session:hangup(); -- default normal_clearing


session:hangupCause

You can find the hangup cause of an answered call and/or the reason an originated call did not complete. See Hangup causes.


-- Initiate an outbound call

obSession = freeswitch.Session("sofia/192.168.0.4/1002")

-- Check to see if the call was answered

if obSession:ready() then
    -- Do something good here

else    -- This means the call was not answered ... Check for the reason

    local obCause = obSession:hangupCause()

    freeswitch.consoleLog("info", "obSession:hangupCause() = " .. obCause )

    if ( obCause == "USER_BUSY" ) then              -- SIP 486
       -- For BUSY you may reschedule the call for later
    elseif ( obCause == "NO_ANSWER" ) then
       -- Call them back in an hour
    elseif ( obCause == "ORIGINATOR_CANCEL" ) then   -- SIP 487
       -- May need to check for network congestion or problems
    else
       -- Log these issues
    end
end

session:hangupState

session:mediaReady

session:originate

session:playAndGetDigits

Play a file and get digits:

  • The call has to be answered before any DTMF will be read. If you do not answer the call you will still hear the file being played, but no functionality will be available.
  • No DTMF is read while bad_input_audio_file is being played. DTMF is only read when playing audio_files (using variable names as show in the example below)
digits = session:playAndGetDigits(2, 5, 3, 3000, "#", "/sr8k.wav", "", "\\d+");
freeswitch.consoleLog("info", "Got dtmf: ".. digits .."\n");              

This has 8 arguments: min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_file, digits_regex

Note: If you need to match the * key in the regexp, you will have to quote it twice, as in:

digits = session:playAndGetDigits(2, 5, 3, 3000, "#", "/sr8k.wav", "", "\\d+|\\*");

session:preAnswer

Pre answer the session:

session:preAnswer();

session:read

Play a file and get digits.

digits = session:read(5, 10, "/sr8k.wav", 3000, "#");                                                                                                           
freeswitch.consoleLog("info", "Got dtmf: ".. digits .."\n");         

session:read has 5 arguments: <min digits> <max digits> <file to play> <inter-digit timeout> <terminators>

session:ready

See #session:hangupCause for more detail on if NOT ready.

while (session:ready() == true) do                                                                                                                              
   -- do something here                                                                                                                                              
end 

session:recordFile

syntax is session:recordFile(file_name, max_len, silence_threshold, silence_secs)

silence_secs is the amount of silence to tolerate before ending the recording.

Example:

session:recordFile("/tmp/blah.wav", 30000, 10, 10);  -- use inputcallback to end recording.                                                                                                           
session:streamFile("/tmp/blah.wav"); 


'''NOTE:'''
if you want the old behaviour of pressing "#" to stop the recording use somthing like the following input callback (the input callback returns "break"):
  function onInput(s, type, obj) 
  if (type == "dtmf" and obj['digit'] == '#') then 
      return "break"; 
  end 
end 

session:answer(); 
session:setInputCallback("onInput", ""); 
session:recordFile("/tmp/blah.wav", 30000, 10, 10); -- pressing # ends the recording 
session:streamFile("/tmp/blah.wav"); 
session:hangup();

--Another one
function onInputEntradaAudio(session, tipoEntrada, contenedor, argumentos)
  local tonosDeParo = {};
  tonosDeParo = Utils:commaText(argumentos[1]);
  if (tipoEntrada == "dtmf") then  
   for k, v in pairs(tonosDeParo) do
    if (contenedor['digit'] == v) then return "break"; end
   end
  end
end

table.insert(argumentosX, "*, #");
session:setInputCallback("onInputEntradaAudio", "argumentosX"); 
session:recordFile(path, segundosMax, umbralSilencio, segundosInterrupcion);

session:sayPhrase

Play a speech phrase macro.

session.sayPhrase(macro_name [,macro_data] [,language]);
  • macro_name - (string) The name of the say macro to speak.
  • macro_data - (string) Optional. Data to pass to the say macro.
  • language - (string) Optional. Language to speak macro in (ie. "en" or "fr"). Defaults to "en".

To capture events or DTMF, use it in combination with session:setInputCallback

Example:

function key_press(session, input_type, data, args)
  if input_type == "dtmf" then
    freeswitch.consoleLog("info", "Key pressed: " .. data["digit"])
    return "break"
  end
end
if session:ready() then
  session:answer()
  session:execute("sleep", "1000")
  session:setInputCallback("key_press", "")
  session:sayPhrase("voicemail_menu", "1:2:3:#", "en")
end

When used with setInputCallback, the return values and meanings are as follows:

  • true or "true" - Causes prompts to continue speaking.
  • Any other string value interrupts the prompt.


session:sendEvent

session:setAutoHangup

By default, lua script hangs up when it is done executing. If you need to run the next action in your dialplan after the lua script, you will need to setAutoHangup to false. The default value is true.

session:setAutoHangup(false)

session:setHangupHook

In your lua code, you can use setHangupHook to define the function to call when the session hangs up.

function myHangupHook(s, status, arg)
    freeswitch.consoleLog("NOTICE", "myHangupHook: " .. status .. "\n")
    -- close db_conn and terminate
    db_conn:close()
    error()
end

blah="w00t";

session:setHangupHook("myHangupHook", "blah")

session:setInputCallback

function my_cb(s, type, obj, arg)                                                                                                                                  
                                                                                                                                                                
   if (arg) then                                                                                                                                                
      io.write("type: " .. type .. "\n" .. "arg: " .. arg .. "\n");                                                                                             
   else                                                                                                                                                         
      io.write("type: " .. type .. "\n");                                                                                                                       
   end                                                                                                                                                          
                                                                                                                                                                
   if (type == "dtmf") then                                                                                                                                     
      io.write("digit: [" .. obj['digit'] .. "]\nduration: [" .. obj['duration'] .. "]\n");                                                                     
   else                                                                                                                                                         
      io.write(obj:serialize("xml"));                                                                                                                           
                                                                                                                                                                
      e = freeswitch.Event("message");                                                                                                                          
      e:add_body("you said " .. obj:get_body());                                                                                                                
      session:sendEvent(e);                                                                                                                                     
   end                                                                                                                                                          
end                                                                                                                                                             

blah="w00t";                                                                                                                                                                
                                                                                                                                                                
session:answer();                                                                                                                                               
session:setInputCallback("my_cb", "blah");                                                                                                                      
session:streamFile("/tmp/swimp.raw");          

session:setVariable

Set a variable on a session:

session:setVariable("varname", "varval");

session:sleep

session:sleep(3000); 
  • This will allow callbacks to DTMF to occur and session:execute("sleep", "5000"), won't.

session:speak

session:set_tts_parms("flite", "kal");
session:speak("Please say the name of the person you're trying to contact");

session:say

Plays pre-recorded sound files for things like numbers, dates, currency, etc. Refer to Misc. Dialplan Tools say for info about the say application.

Arguments: <data><lang><say_type><say_method>

Example:

session:say("12345", "en", "number", "pronounced");

session:streamFile

Stream a file to the session

session:streamFile("/tmp/blah.wav");

session:transfer

Transfer the current session. The arguments are extensions, dialplan and context.

session:transfer("3000", "XML", "default");

execution of your lua script will immediately stop, make sure you set session:setAutoHangup(false) if you don't want your call to disconnect


session:unsetInputCallback

session:unsetInputCallback()


session:waitForAnswer

Non-Session API

These methods are generic in that they do not apply to a session or an event. For example, printing data to the FreeSWITCH console is neither event- nor session-specific.

freeswitch.API

api = freeswitch.API();

freeswitch.bridge

session1 = freeswitch.Session("sofia/internal/1001%192.168.1.1");
session2 = freeswitch.Session("sofia/internal/1002%192.168.1.1");
freeswitch.bridge(session1, session2);

freeswitch.consoleCleanLog

freeswitch.consoleCleanLog("This Rocks!!!\n");

freeswitch.consoleLog

Log something to the freeswitch logger. Arguments are loglevel, message.

freeswitch.consoleLog("info",   "lua rocks\n");
freeswitch.consoleLog("notice", "lua rocks\n");
freeswitch.consoleLog("err",    "lua rocks\n");
freeswitch.consoleLog("debug",  "lua rocks\n");
freeswitch.consoleLog("warning","lua rocks\n");

freeswitch.Event

This is firing a custom event my::event.

local event = freeswitch.Event("custom", "my::event"); 
event:addHeader("My-Header", "test");
event:fire();
--Another one
function FSMan:fire(nombreHeader, header, body)--Manda un evento MESSAGE a algun receptor
  local miEvento = freeswitch.Event("MESSAGE");
  nombreHeader = Utils:trim(nombreHeader); header = Utils:trim(header); body = Utils:trim(body);
  if (nombreHeader == false ) then nombreHeader="Nombre_Header_Generico" end
  if (header == false) then header="Header_Generico" end
  if (body == false) then body="Body_Generico" end
  miEvento:addHeader(nombreHeader, header);
  miEvento:addBody(body);
  miEvento:fire();
end

freeswitch.EventConsumer

Consumes events from FreeSWITCH.

Usage:

con = freeswitch.EventConsumer("all");

-- pop() returns an event or nil if no events
con:pop();

-- pop(1) blocks until there is an event
con:pop(1);

Example:

con = freeswitch.EventConsumer("all");                                                                                                                          
                                                                                                                                                                
session = freeswitch.Session("sofia/default/dest@host.com");                                                                                                                                                                                                                                                                    

while session:ready() do                                                                                                                                        
   session:execute("sleep", "1000");                                                                                                                            
   for e in (function() return con:pop() end) do                                                                                                                
      print("event\n" .. e:serialize("xml"));                                                                                                                      
   end                                                                                                                                                          
end      

freeswitch.IVRMenu

hash = {                                                                                                                                                        
   ["main"] = undef,                                                                                                                                            
   ["name"] = "top",                                                                                                                                            
   ["greet_long"] = "phrase:demo_ivr_main_menu",                                                                                                                
   ["greet_short"] = "phrase:demo_ivr_main_menu_short",                                                                                                            
   ["invalid_sound"] = "ivr/ivr-that_was_an_invalid_entry.wav",                                                                                                                          
   ["exit_sound"] = "voicemail/vm-goodbye.wav",                                                                                                                 
   ["confirm_macro"] = "undef",                                                                                                                                 
   ["confirm_key"] = "undef",                                                                                                                                   
   ["confirm_attempts"] = "3",                                                                                                                                  
   ["inter_digit_timeout"] = "2000",                                                                                                                            
   ["digit_len"] = "1",                                                                                                                                         
   ["timeout"] = "10000",                                                                                                                                       
   ["max_failures"] = "3"                                                                                                                                       
}                                                                                                                                                               
                                                                                                                                                                
top = freeswitch.IVRMenu(hash["main"],                                                                                                                          
                         hash["name"],                                                                                                                          
                         hash["greet_long"],                                                                                                                    
                         hash["greet_short"],                                                                                                                   
                         hash["invalid_sound"],                                                                                                                 
                         hash["exit_sound"],                                                                                                                    
                         hash["confirm_macro"],                                                                                                                 
                         hash["confirm_key"],                                                                                                                   
                         hash["confirm_attempts"],                                                                                                              
                         hash["inter_digit_timeout"],                                                                                                           
                         hash["digit_len"],                                                                                                                     
                         hash["timeout"],                                                                                                                       
                         hash["max_failures"]);                                                                                                                 
                                                                                                                                                                
top:bindAction("menu-exec-app", "playback /tmp/swimp.raw", "2");                                                                                                
top:execute(session, "top");                          


When using SAY, 3 additional variables have to be set or you will get the following error:

> [ERR] mod_lua.cpp:182 Error in IVRMenu expected 16..16 args, got 13 stack traceback:
> [C]: in function 'IVRMenu'
> /usr/local/freeswitch/scripts/ivr.lua:19: in main chunk

These variables are:

    ["tts_engine"]          = "flite",
    ["tts_voice"]           = "rms",
    ["max_timeouts"]        = "2"

freeswitch.msleep

Tells script to sleep for a specified number of milliseconds.
NOTE: Do not use this on a session-based script or bad things will happen.

  -- Sleep for 500 milliseconds
  freeswitch.msleep(500);

freeswitch.Session

Create a new session.

local session = freeswitch.Session("sofia/10.0.1.100/1001");
session:transfer("3000", "XML", "default"); 

Create a new session with execute_on_answer variable set.

local session = freeswitch.Session("[execute_on_answer=info notice]sofia/10.0.1.100/1001");

stream:write

stream:write("Content-Type: text/html\n\n");
stream:write("<title>FreeSWITCH Command Portal</title>");
stream:write("<h2>FreeSWITCH Command Portal</h2>");
stream:write("<form method=post><input name=command size=40> ");
stream:write("<input type=submit value=\"Execute\">");
stream:write("</form><hr noshade size=1><br>");

command = env:getHeader("command");

if (command)  then
   api = freeswitch.API();
   reply = api:executeString(command);

   if (reply) then
      stream:write("<br><B>Command Result</b><br>" .. reply .. "\n");
   end

end

env:addHeader("cool", "true");
stream:write(env:serialize() .. "\n\n");

Special Case: env object

When lua is called as the hangup hook there will be a special env object that contains all the channel variables from the channel that just disconnected.

Add an extension to test this feature:

 <extension name="lua-env-hangup-hook-test">
   <condition field="destination_number" expression="^(1234)$">
     <action application="answer"/>
     <action application="set" data="api_hangup_hook=lua hook-test.lua"/>
     <action application="set" data="my_custom_var=foobar"/> 
     <action application="sleep" data="10000"/>
     <action application="hangup"/>                   
   </condition>                             
 </extension>

Then add freeswitch/scripts/hook-test.lua:

-- hook-test.lua                 
-- demonstrates using env to look at channel variables in hangup hook script

-- See everything
dat = env:serialize()            
freeswitch.consoleLog("INFO","Here's everything:\n" .. dat ..\nn")

-- Grab a specific channel variable
dat = env:getHeader("uuid")      
freeswitch.consoleLog("INFO","Inside hangup hook, uuid is: " .. dat .. "\n")                            

-- If you created a custom variable you can get it also...
dat = env:getHeader("my_custom_var")
freeswitch.consoleLog("INFO","my_custom_var is '" .. dat .. "'\n")

Watch the FS console and dial 1234 and then hangup. You'll see all your channel variables!

See Also

Personal tools
Community
Support FreeSWITCH