Mostrando entradas con la etiqueta lista. Mostrar todas las entradas
Mostrando entradas con la etiqueta lista. Mostrar todas las entradas

martes, 28 de agosto de 2012

Como hacer un Autodialer para Asterisk


Hola, antes de continuar, quiero decirles que he trabajado en una nueva forma de hacer el marcador automático, con intertefaz web, en fin, mucho mejor. Pueden encontrar más información aquí.

En esta entrada les explicaré como escribir un Auto Dialer sencillo en Java. 
Como requerimiento, es necesario estar familiarizado con Asterisk, la forma en que trabaja su dial plan y también conocimiento en el lenguaje de programación Java. 

Con algunas modificaciones, luego podrían hacer alguna de las siguientes cosas:
  • Agendar un cron job que ejecute el programa en algún momento del día, por ejemplo, como llamada de  despertador.
  • Hacer una difusión masiva de un mensaje de audio, hacia una lista de números.
  • Realizar una campaña de marketing, donde se realicen llamadas y se haga preguntas de opción múltiple que se puedan responder marcando un digito.
  • Leer una lista de números desde una base de datos, etc.
Éstas son sólo algunas ideas, pero hay muchas posibilidades.

Los call files de Asterisk
Son archivos que, básicamente, contienen las instrucciones para realizar una llamada. Colocados en el directorio correcto, son detectados por Asterisk y éste ejecuta las instrucciones escritas en el archivo.

Estrategia para abordar el problema
Nuestra estrategia será escribir una aplicación Java que produzca estos archivos en un directorio temporal y luego los copie al directorio /var/spool/asterisk/outgoing/, de forma que Asterisk los pueda procesar. 

Es en realidad algo muy sencillo que luego podemos ir armando con mayor grado de complejidad y opciones según nuestra necesidad.

Sintaxis de un call file para reproducir un mensaje (o ejecutar una aplicación)
Tomado de http://www.voip-info.org, tan sólo lo traduje al español:
Especificar cómo y dónde llamar:
  • Channel: <canal>: Canal a utilizar para la llamada.
  • CallerID: "nombre" <número> Identificador de quien llama, Por favor notar: Puede no funcionar si no se respeta el formato: CallerID: "Un nombre" <1234>
  • MaxRetries: <número> Número de reintentos antes que la llamada falle (sin incluir el intento inicial, por ejemplo 0 es igual a un intento en total de realizar la llamada). El valor por defecto es 0.
  • RetryTime: <número> Segundos entre los reintentos, No insistir tan seguido sobre un teléfono que no está disponible. El valor por defecto es 300 (5 min).
  • WaitTime: <número> Segundos para esperar que la llamada sea contestada. El valor por defecto es 45.
  • Account: Poner el valor de cuenta a utilizar.
Si la llamada es contestada, conectarla aquí:
  • Context: <nombre del contexto> Un contexto en el archivo extensions.conf
  • Extension: <extensión> Una extensión definida en el archivo extensions.conf
  • Priority: <prioridad> La prioridad de la extensión desde donde se iniciará la conexión.
  • Set: Poner una variable para utilizar el la lógica del contexto (eejmplo: file1=/tmp/to ); en Asterisk 1.0.x usamos 'SetVar' en lugar de 'Set'
  • Application: Aplicación de Asterisk a ser ejecutada (se utiliza en lugar de especificar context, extension y priority)
  • Data: Las opciones a ser pasadas a la aplicación.
Nuevo (?) en Asterisk 1.4
  • Set: Puede ahora también escribir a funciones del dialplan como CDR()
  • AlwaysDelete: Yes/No -Si la fecha y tiempo de modificación del archivo es el futuro, el archivo de llamada no será borrado.
  • Archive: Yes/No - Mover hacia el subdirectorio "outgoing_done" con "Status: value", donde value puede ser Completed, Expired o Failed.
 Entonces, tenemos dos opciones, referenciar un contexto/extensión/prioridad que exista en nuestro archivo extensions.conf, o podemos invocar una Aplicación de Asterisk indicando sus parámetros.

Prerequisitos para probar el Demo.
  • Una instalación Ubuntu o CentOS donde se esté ejecutando Asterisk.
  • Si deseamos realizar llamadas hacia la PSTN, debemos tener configurada una troncal que nos permita hacer esto.
  • Un archivo de audio en el directorio /var/lib/asterisk/sounds/ llamado mensaje.gsm con algún mensaje de prueba que se reproducirá para las personas que contesten nuestras llamadas.
  •  Tener JDK instalado (se puede si está instalado con el comando java -version, caso contrario instalar).
  • Creamos el directorio /var/spool/asterisk/tmp/
  • Disponer de credenciales con privilegios en la instalación Ubuntu.
Ahora, creamos un archivo, que llamaremos AutoDialerDemo.java.

Como mencioné anteriormente, debemos tener creado el directorio /var/spool/asterisk/tmp/y el usuario que ejecute la aplicación debe tener permiso de escritura sobre el mismo (debería ser super usuario para descomplicar la explicación).
    //Directorio donde se crearán inicialmente los archivos
    private static final String TMP_DIR_PATH = "/var/spool/asterisk/tmp";
Utilizaremos un archivo que llamaremos prueba.cfg, que debe encontrarse en el mismo directorio que nuestro archivo AutoDialerDemo.java.
      
    //Al ejecutar la aplicación, se debe pasar como parámetro el nombre del archivo de configuración (por ejemplo prueba.cfg)
    generarLlamadas(args[0]);



Un ejemplo del contenido de nuestro archivo prueba.cfg sería:

    app.proveedor=TuProveedor
     app.numero_0=1234UnNumeroComoLoEsperaTuProveedor
     app.numero_1=1234OtroNumeroComoLoEsperaTuProveedor    
     app.numero_2=1159393260807EnMiCaso
     ...
     app.numero_9=1234UltimoNumeroComoLoEsperaTuProveedor


Finalmente, creamos un archivo .call por cada número en la lista, y lo estructuramos con los datos especificados en el archivo prueba.cfg:

           //Asignamos el nombre del archivo
            file = new File(tmpDir, filename + ".call");

            writer = new BufferedWriter(new FileWriter(file));

            String text = "";
          
            //Especificamos el canal, en este caso, la llamada que realizaremos
            text = "Channel: SIP/" + proveedor + "/" + numero;
            writer.write(text);
            writer.newLine();
          
            System.out.println(text);
          
            //Además del intento inicial, realizaremos un reintento si la llamada no es conectada
            text = "MaxRetries: 1";
            writer.write(text);
            writer.newLine();

            //El reintento lo realizaremos 60 segundos después del intento inicial, de ser el caso
            text = "RetryTime: 60";
            writer.write(text);
            writer.newLine();

            //Esperaremos 30 segundos a que nuestra llamada sea contestada
            text = "WaitTime: 30";
            writer.write(text);
            writer.newLine();

            //Una vez contestada, reproduciremos un mensaje
            text = "Application: Playback";
            writer.write(text);
            writer.newLine();
          
            //El mensaje a reproducir será el audio en el archivo mensaje.gsm
            //Recuerda que este archivo debe estar en el directorio /var/lib/asterisk/sounds
          
            text = "Data: mensaje";
            writer.write(text);
            writer.newLine();

Copiamos el archivo generado desde el directorio /var/spool/asterisk/tmp hacia el directorio /var/spool/asterisk/outogoing. Lo hacemos de esta forma para que asterisk no intente procesar un archivo incompleto:

             //Damos permisos al usuario asterisk sobre nuestro archivo
             Runtime.getRuntime().exec("chown asterisk:asterisk /var/spool/asterisk/tmp/" + filename + ".call");
             //Movemos el archivo desde el directorio temporal hacia el directorio donde asterisk lo procesará
             Runtime.getRuntime().exec("mv /var/spool/asterisk/tmp/" + filename + ".call /var/spool/asterisk/outgoing/" + filename + ".call");

        

 Compilamos el archivo java ejecutando el siguiente comando en la terminal:
     $ javac AutoDialerDemo.java

Y obtenemos el archivo AutoDialerDemo.class. Luego, asumiendo que el archivo prueba.cfg se encuentra en el mismo directorio que AutoDialerDemo.class, y que la información en él es correcta, ejecutamos:
     $ java AutoDialerDemo prueba.cfg

Aconsejo tener otra ventana de terminal abierta conectada al CLI de Asterisk, de forma que podamos ver qué sucede tanto en la salida de nuestra aplicación como en los mensajes de Asterisk.

Incluyo el archivo AutoDialerDemo.java.
¡Suerte con estas llamadas autogeneradas! Sólo intenta no hacer tus pruebas en el horario en que otros descansan zzz.