Events

Ben Langfeld edited this page Apr 11, 2012 · 15 revisions

DEPRECATION NOTICE: This is old documentation relevant to Adhearsion 1.x and will soon be removed. See the main documentation for up-to-date info.

Asterisk makes a large set of events available via the Manager API. In turn, Adhearsion has a rich and very useful events subsystem; this allows you to define custom handlers for callbacks exposed by either Adhearsion itself or by an Adhearsion component you're using. When these callbacks are asynchronously triggered, they utilize a Thread pool so, ideally, the occasional long-running task won't lock up the throughput of events too much.

##events.rb##

When you create a new Adhearsion application, notice the file in the root directory of the app called events.rb. This file is yours to freely modify by registering callbacks with the namespaces you may have available. For example, a namespace could be something such as:

  • /asterisk/before_call
  • /shutdown
  • /xmpp/my_username/incoming_message

When one part of the framework must notify another part of the framework of something, it should go through this events subsystem. The /xmpp/my_username/incoming_message example above shows how a hypothetical XMPP component might allow you to receive incoming messages asynchronously.

A sample callback definition in events.rb looks like this:

events.asterisk.before_call.each do |call|
  extension = call.variables[:extension]
  ahn_log "New call with extension #{extension}"
end

Notice how, for this namespace (the /asterisk/before_call namespace), a Call object is passed in case your callback wants to use its behavior or state somehow.

##Dealing with all Events##

You may process each event as it comes into the events.rb file and then evaluate the events as follows:

events.asterisk.manager_interface.each do |event|
  case event.name.downcase
  when "hangup"
    ahn_log "Hung up @ #{Time.now}"
  when "newchannel"
    #do something
  end
end

##Events Available in Asterisk##

Can be found here.

##Using Events Outside of Adhearsion##

If you are using Adhearsion's ManagerInterface in a separate script, you may want enable events and handle them without using Theatre. To do this, simply subclass ManagerInterface and override the event_message_received() method. The method takes one argument that receives an instance of ManagerInterfaceEvent each time Asterisk sends an event.

class MyManagerInterface < Adhearsion::VoIP::Asterisk::Manager::ManagerInterface
  def event_message_received(event)
    if(event.kind_of? Adhearsion::VoIP::Asterisk::Manager::ManagerInterfaceEvent )
      puts event.inspect
    end
  end
end

MyManagerInterface.connect ......
# some kind of loop or daemon here

##Custom Events with AGI command UserEvent##

It is possible to use the AGI command UserEvent to send custom events for processing by the Adhearsion events subsystem. However, you must follow a particular format or you risk corrupting the event parsing, which would then stop Adhearsion from processing any further events for that session (see ticket #58). This is unavoidable due to the lack of protocol enforcement by Asterisk.

To create a simple, named UserEvent use syntax like this:

exten => _X.,1,UserEvent(MyCustomEvent)

The above example will create a UserEvent named MyCustomEvent without any additional information. This is the safest way to use UserEvents.

It is also possible to send UserEvents with custom data in the event body. This is where you need to be more careful. To send a UserEvent with custom information you must follow this format:

exten => _X.,1,UserEvent(MYEVENT,key1:value,key2:value)

The key here is that you must use key/value pairs and you must separate key/value pairs with a colon (':'). This will then create an event in events.rb that will look like this:

INFO event_logger: Adhearsion::VoIP::Asterisk::Manager::ManagerInterfaceEvent:
#<Adhearsion::VoIP::Asterisk::Manager::ManagerInterfaceEvent:0x177611c
@headers={"Privilege"=>"user,all", "key1"=>"value", "key2"=>"value", "UserEvent"=>"MYEVENT"},
@name="UserEvent">

Any non-standard syntax in the body of the UserEvent will likely cause a protocol error. Depending on the nature of the protocol error this may cause Adhearsion to cease processing the events feed. A restart of Adhearsion may be necessary to fix the problem.