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.
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.
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";
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.
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
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
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.
Hola amigo gracias por el aporte, existe alguna interfaz Grafica?
ResponderEliminarHola Bryan, cuando desarrollé esto no lo hice con interfaz gráfica. Te comento que volví a desarrollar una solución para generar llamadas automáticas pero esta vez basado en Asterisk Manage Interface (AMI). Espero publicarla pronto.
EliminarHola Alex!! espero que bien hermano, esperando con ansias tu publicación sobre AMI
EliminarHola Alex!! espero que bien hermano, esperando con ansias tu publicación sobre AMI
EliminarHola Alex,
ResponderEliminar¿Como puedo colgar una llamada saliente creada mediante un call file? Se que poniendo en consola "sip show channels" me salen las llamadas activas pero no se cual es el canal para poder colgarla.
Un saludo
No he revisado el tema de colgar llamadas generadas por archivo. Depende de la aplicación de tus llamadas, es decir, por qué razón deberían de quedar abiertas luego de su propósito? (por ejemplo, reproducir un archivo de audio). Lo más seguro es siempre agregar un "Application: Hangup" al final.
EliminarTe comento que volví a desarrollar una solución para generar llamadas automáticas pero esta vez basado en Asterisk Manage Interface (AMI). Espero publicarla pronto.
Muchas gracias Alex por tu pronta respuesta. La razón de querer forzar a colgar una llamadas es simplemente por comodidad a la hora de probar aplicaciones, por ejemplo, de encuestas telefónicas automáticas. Ya que si salta un buzon de voz, la llamada se queda pillada hasta que termina el buzon.
EliminarHe buscado por google, pero no encuentro la manera de forzar a colgar estas llamadas.
Muchas gracias!
Hola como estás, por un desarrollo en el que he estado trabajando me topé con esto de cerrar llamadas si te contesta un buzón de voz. Hay una aplicación en asterisk que se llamada AMD (por answering machine detection). Creo que esto te podría servir para lo que necesitabas hacer. Espero que no sea tarde!
EliminarTengo una versión mejorada para la generación atuomática de llamadas telefónicas, pueden encontrar mayor información en http://www.iveloper.com/marcador-automatico-de-llamadas-vocero/
ResponderEliminarSaludos!
Alex, me gustaria revisar su proyecto en mención, cualquier cosa me puede escribir a mi correo yogui801@msn.com
Eliminar