Tutorial on Linux + Asterisk +MySQL + Java – part 4

This part of the tutorial keep going with the explanation of the Asterisk-Java’ Live API.

We concluded the previous part of the tutorial talking of Manager API. Now it is time to talk of the Live API.
This API provide an *abstraction* layer over the Manager API, making available *objects* representing Asterisk’ components, instead of directly send commands to the AMI. Some of this *objects* are AsteriskChannel (it represents a channel inside Asterisk), AsteriskServer (the Asterisk server itself) and so on. You may find them inside the org.asteriskjava.live package.
In the following example we tell asterisk to call a (connected) SIP client and, if it answer, redirect it to a specific extension. First of all we have to login to the AMI, as we did in the previous part:

        ManagerConnectionFactory factory = new ManagerConnectionFactory(
				"localhost", "admin", "secret5");
	// Retrieve the connection from the factory
	ManagerConnection managerConnection = factory.createManagerConnection();
	try {
		// login to Asterisk
		managerConnection.login();
         ...

then we instantiate an AsteriskServerImpl that “represent” the Asterisk server:

AsteriskServerImpl asteriskServer = new AsteriskServerImpl(managerConnection);

Now, we want to be sure to call a client actually connected, so:

  1. first, we retrieve the list or configured peers
  2. iterate over them and select the first (if any) is currently connected
  3. if no peer is connected, the method return
  4. otherwise, we retrieve the peer’ channel
  5. and then call it and, eventually, redirect it to a specific context/extension/priority
        // Retrieve the list of configured peers
	List peerEntries = asteriskServer.getPeerEntries();
	PeerEntryEvent peerToCall = null;
        // Iterate over peers
	for (PeerEntryEvent peerEntry : peerEntries) {
		String status = peerEntry.getStatus();
                // Select the first one connected and exit the loop
		if (status != null && status.contains("OK")) {
		         peerToCall = peerEntry;
                         break;
		}
	}
        // If no peer is connected exit from method
	if (peerToCall == null) {
		return;
	}
        // Build the channel name
	String channelName = peerToCall.getChannelType();
	channelName += "/" + peerToCall.getObjectName();
        // Call the client and, eventually, redirect it
	asteriskServer.originateToExtension(channelName, "default", "8600", 1, 10000);

originateToExtension is just one of the methods that AsteriskServerImpl offers. As a side note, it throws an Exception if the “originate” action cannot be sent to the Asterisk server or if the channel name is unavailable. A nice thing is that this method returns an AsteriskChannel that may be used for funny stuff, like for example send a DTMF to the peer:

         AsteriskChannel asteriskChannel = asteriskServer.originateToExtension(channelName, "default", "8600", 1, 10000);
	asteriskChannel.playDtmf("1");

In my dialplan 8600@default is a MeetMe conference – I am using this for the example so to be sure that the channel is still active when we send the DTMF.
As I have already told you at the beginning of the tutorials (or maybe not, I’m getting older), I am not an Asterisk GURU, but here I would just put a quick checklist to verify that you have a correct MeetMe configuration (thanks Jorge for your suggestion):

  1. Meetme depends on dahdi; so dahdi module should be loaded (on linux, check with lsmod | grep dahdi); moreover, dahdi channels must be owned by the user that *actually* run asterisk – to be clear, I start asterisk as root but the asterisk process is owned by “asterisk” user (ps aux | grep asterisk); so, all /dev/dahdi “devices” (and the directory itself) must be owned by “asterisk” user;
  2. inside meetme.conf you just have to put a line like “conf => (number of conference, ex. 1234);
  3. of course, you have to load MeetMe module on Asterisk (you can check it for example from console with “meetme list” command; it actually shows only active conferences, so it is normal you have an empty return);
  4. you have to create a dialplan extensions that point to the meetme conference (ex. exten => 8600,1,Meetme(1234));
  5. verify that everything is working with a sip phone calling the extension (in the example, 8600) – you should be able to join the conference (and now the conference should appear with the “meetme list” command).

And here’s the complete code to use:

package net.cardosi.asterisk.live;

import java.util.List;
import org.asteriskjava.live.AsteriskChannel;
import org.asteriskjava.live.internal.AsteriskServerImpl;
import org.asteriskjava.manager.ManagerConnection;
import org.asteriskjava.manager.ManagerConnectionFactory;
import org.asteriskjava.manager.event.PeerEntryEvent;

public class LiveTest {

	public static void main(String[] args) {
		// Retrieve the factory with connection parameters
		ManagerConnectionFactory factory = new ManagerConnectionFactory(
				"localhost", "admin", "secret5");
		// Retrieve the connection from the factory
		ManagerConnection managerConnection = factory.createManagerConnection();
		try {
			// login to Asterisk
			managerConnection.login();
			// Instantiate a new AsteriskServer
			AsteriskServerImpl asteriskServer = new AsteriskServerImpl(
					managerConnection);
			// Retrieve the list of configured peers
			List peerEntries =                                asteriskServer.getPeerEntries();
			PeerEntryEvent peerToCall = null;
			// Iterate over peers
			for (PeerEntryEvent peerEntry : peerEntries) {
				String status = peerEntry.getStatus();
				// Select the first one connected and exit the loop
				if (status != null && status.contains("OK")) {
					peerToCall = peerEntry;
					break;
				}
			}
			// If no peer is connected exit from method
			if (peerToCall == null) {
				return;
			}
			String channelName = peerToCall.getChannelType();
			channelName += "/" + peerToCall.getObjectName();
			System.out.println("Calling " + channelName);
			AsteriskChannel asteriskChannel = 
                           asteriskServer.originateToExtension(channelName, "default",   "8600", 1, 10000);
			Thread.sleep(10000);
			System.out.println("Playing '1' on " + channelName);
			asteriskChannel.playDtmf("1");
		} catch (Exception e) {
			// Manage exception
			e.printStackTrace();
		}
	}
}

To test the code, you have to verify the settings like in the previous part. Moreover, you have to configure an extension in your dialplan that keep the channel active (MeetMe, ConfBridge, ParkedCall).
And that’s all for now. In the next part we will have some fun with EventListeners. Don’t miss that!!! Bye

Author: gabrio12

Java developer, amateur recorder player, what else...?

11 thoughts on “Tutorial on Linux + Asterisk +MySQL + Java – part 4”

  1. It would be great if we can have a simple tutorial explaining how to make call between two clients, both of them registered on different asterisk servers.

    Like

  2. Thank you very much for your tutorials. Are really great. They are helping me a lot.
    Could you tell me how did you configured the MeetRoom? I have done (in the wrong way I think) and I get this error when I call :
    org.asteriskjava.live.NoSuchChannelException: Channel ‘DAHDI/g0/XXXXXX’ is not available
    at org.asteriskjava.live.internal.AsteriskServerImpl.originate(AsteriskServerImpl.java:312)
    at org.asteriskjava.live.internal.AsteriskServerImpl.originateToExtension(AsteriskServerImpl.java:250)
    at org.asteriskjava.live.internal.AsteriskServerImpl.originateToExtension(AsteriskServerImpl.java:228)
    at …

    Like

    1. Hi Jorge,
      thanks for your nice words.
      I will take the chance of your question for a quick check list to verify that a meetme configuration is working.
      1) Meetme depends on dahdi; so dahdi module should be loaded (on linux, check with lsmod | grep dahdi); moreover, dahdi channels must be owned by the user that *actually* run asterisk – to be clear, I start asterisk as root but the asterisk process is owned by “asterisk” user (ps aux | grep asterisk); so, all /dev/dahdi “devices” (and the directory itself) must be owned by “asterisk” user
      2) inside meetme.conf you just have to put a line like “conf => (number of conference, ex. 1234)
      3) of course, you have to load MeetMe module on Asterisk (you can check it for example from console with “meetme list” command; it actually shows only active conferences, so it is normal you have an empty return);
      4) you have to create a dialplan extensions that point to the meetme conference (ex. exten => 8600,1,Meetme(1234) )
      5) verify that everything is working with a sip phone calling the extension (in the example, 8600) – you should be able to join the conference (and now the conference should appear with the “meetme list” command)
      6) in your code, you have to “originateToExtension” between a connected client and the extensions configured for meetme (in the example, 8600); please note that the first parameter of originateExtension is the channel name of a CONNECTED client (for a sip client it is like “SIP/XXXX”);
      7) I could recreate the same error both putting as channel a not connected client and a not existing one; so, my first guess would be that “g0/XXXXXXX” was not connected or “wrongly” named
      Hope to have been of any help.
      Best

      Like

  3. Hi:
    Thank you so much for your help. The problem was the point 2. I didn´t add it. Please, could you add the explanation in the comment to the tutorial?.
    Please, keep adding more tutorials like this.

    Like

    1. Well,
      if you ask so kindly I’ll do :). Actually, since Asterisk configuration is a HUGE topic, I tried to focus mostly on the code. But it seems I was wrong, and more explanation are helpful here.
      Best

      Like

Leave a comment