fibaro domotica razberry z-wave

Razberry: Domotica low-cost existe gracias a Z-Wave

Es curioso porque cuando compré mi placa Razberry Z-Wave tenía ciertas dudas si conseguiría que funcionase algo con todo esto de la Domotica. Como comentaba en el anterior artículo, todo mi interés surgió cuando me dispuse a investigar sobre soluciones de Smart Metering y vi que los productos completos en el mercado eran excesivamente caros para mi gusto. De pronto, me encontré con los Fibaro Wall-Plugs: Ese tipo de medidores que llaman a la vista por ser excepcionalmente pequeños, y que al parecer, cumplían el objetivo! Con eso solo faltaba el controlador Z-Wave, y por menos de 200 euros, bastante difícil bajarse del burro: Hasta que localice el Razberry Z-Wave 2 por 1: Una interfaz con una API REST y realizaba la función al milímetro. Pero como suelen decir: las gangas no existen, y necesitaba comprobarlo con mis propios ojos, así que hice el pedido (que por cierto, sorprendentemente llego en poco más de un día a través de la tienda online zwave.es y yo esperaba que esa tarjeta Razberry tardará semanas, o incluso meses por ser relativa como popular). Y con todo el material en casa, me dispuse a montar el sistema

fibaro domotica razberry z-wave

Primero el objetivo: Saber cuánto consumen los distintos dispositivos eléctricos/electrónica de mi casa. Quizá en un futuro gracias a la domotica, sería interesante tener una gráfica de consumo y tal, pero creo que es sería más interesante con un dispositivo que se coloca en el cuadro general y mide el consumo general de toda la casa. Pero para un dispositivo en concreto creo que realmente la gracia está en saber cuánto consume.

Por ejemplo: Ponemos el controlador en la lavadora, ponemos el programa clásico de lavado y podemos observar cuanto ha consumido (a pesar de las especificaciones del fabricante). Ahora mismo estoy comprobando el consumo de los emisores térmicos de mi casa, que tienen fama de “ahorro energético” pero tengo la sensación que no es cierto del todo. Esta es una de las bondades de la domotica.

Configurando la interfaz Domotica del Razberry en nuestra Raspberry Pi

Ahora manos a la obra. En primer lugar vamos a configurar el sistema. Para ello nos hace falta tener una Raspberry Pi a la que conectar la placa Razberry Z-Wave (encima de los 10-pines más pegados a la ranura de la tarjeta SD, aunque una imagen vale más que mil palabras)

raspberry pi z-wave razberry domotica

Si ya tenemos Rasbian instalado (versión wheezy en el momento de escribir este artículo más convenientemente), simplemente tendremos que ejecutar el siguiente comando:

wget -q -O - razberry.z-wave.me/install | sudo bash

Con esto quedan instalados los drivers para la Razberry, y el software al que se accede vía web. Quizá necesario reiniciar el sistema para que el sistema operativo reconozca la tarjeta una vez instalado el driver. A partir de aquí ya podemos acceder a la interfaz web:

http://ip_raspberry_pi:8083/expert/

Ahora tenemos que configurar nuestro Fibaro Wall Plug en el sistema de domotica Razberry Z-Wave. Para ello simplemente conectamos el Wall-Plug al dispositivo eléctrico y la corriente como es lógico, y debería encenderse ya el LED en un color indicando el consumo del dispositivo en cuestión (si está apagado, lo más probable es que los leds estén en un azul muy claro). Simplemente con esta acción, el Fibaro Wall-Plug estará preparado para sincronizar con nuestro Razberry. Para ello desde la interfaz web vamos a Network -> Network Management -> (Re)include device y si todo va bien, debería emparejarse sin problemas (en teoría la señal Z-Wave es de aproximadamente unos 20 metros, por eso si no detecta, es que a lo mejor está demasiado lejos, de todas formas el Fibaro Wall Plug tiene un botón en la parte inferior que permite realizar una sincronización forzada, leer el manual de uso, pero a mi siempre me lo ha detectado a la primera)

fibaro wall plug domotica

En el panel de control Web Razberry Z-Wave vamos a Devices configuration y en la parte inferior derecha pulsamos en Expert mode. En la lista de dispositivos en la parte izquierda debería aparecer nuestro Fibaro Wall-Plug, si picamos sobre el y vamos a la parte inferior de la lista de opciones deberíamos ver un menú desplegable llamado Advanced Actions. Dentro pulsamos en Show Interview Results. Si pulsamos en SensorMultiLevel podemos ver todos los datos necesarios para configurar a continuación un acceso a la API de Razberry Z-Wave fundamental para montar nuestro pequeño programa casero para extraer información del sensor. Esto es aplicable a todos los dispositivos que emparejemos con nuestro dispositivo

zwave web razberry domotica

En mi ejemplo si nos damos cuenta, el acceso al Sensor Multi Nivel de la Razberry, se realiza desde devices[2].instances[0].commandClasses[49].data[4].val (en caso de data hay para elegir el 0 y el 4, como quiero sacar el dato en val que es el consumo en Vatios (W) en el momento concreto, pues elijo el 4 y la propiedad “val”).

Para confirmar que todo va bien, podemos acceder a este valor a través de la API de Razberry a través de la dirección (con la propiedad value al final para que nos devuelva el valor)

http://ip_raspberry_pi:8083/ZWaveAPI/Run/devices[2].instances[0].commandClasses[49].data[4].val.value

Si vemos un valor significa que todo va bien (es posible que los valores cambien de dispositivo a dispositivo, por eso he indicado como yo he llegado a estos valores específicamente)

Programación utilizando la API de Razberry y el Fibaro Wall Plug

Ahora mi objetivo es crear un script en PHP que vaya metiendo en una base de datos cada 5 minutos este valor a través de la librería cURL. Dado que la Raspberry Pi no está para trotes, he decidido usar la base de datos SQLite. Creamos la base de datos con el nombre que queramos que es un fichero al final de cuentas, si ya tenemos SQLite instalado y un servidor web con la extensión de PHP (en mi caso puse apache2 como servidor web que aunque es pesado lo conozco mejor, aunque quizá sería más recomendable lighthttp) podemos crear la base de datos con el comando:

# sqlite3 razberry.db

Luego desde la interfaz sqlite3 podemos crear la tabla por ejemplo “plug” con los comandos clásicos de SQL. Nos van a hacer falta unos 4 campos:

  • Un identificador único INTEGER llamado id con autoincremento (no es fundamental, pero nunca está de mas)
  • Un parámetro tipo DATETIME llamémosle fecha
  • Un parámetro tipo REAL llamado valor
  • Un parámetro tipo INTEGER llamado disp. (tampoco es fundamental, pero es práctico para llevar un control de sucesivos dispositivos específicos y no mezclar datos, aparte que me va a servir para simplificar la programación al máximo a efectos explicativos)

El script en PHP es el siguiente, llamémosle /home/pi/consumo.php

#!/usr/bin/php
<?php
if (!function_exists('curl_init')){
die('Sorry cURL is not installed!');
}
$url = "http://ip_raspberry_pi:8083/ZWaveAPI/Run/devices[2].instances[0].commandClasses[49].data[4].val.value";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
class MiBD extends SQLite3{
function __construct()
{ $this->open('/var/www/razberry.db'); }
}
$bd = new MiBD();
$watios = curl_exec($ch);
$bd->exec("INSERT INTO plug (fecha,valor,disp) VALUES (datetime('now'),$watios,1)");
curl_close($ch);
?>

De aquí solo ver, que hacemos una llamada a la API con cURL para sacar el dato de consumo, y luego insertamos el datos en la tabla junto a la fecha del momento y marcamos el dispositivo número 1 (en este caso el primer dispositivo electrónico que vayamos a medir, luego si cambiamos de sitio el enchufe para domotica Fibaro Wall-plug podemos poner el número 2, 3 y así sucesivamente)

Ahora necesitamos un script para que corra este script en PHP cada 5 segundos, por ejemplo /home/pi/consumo.sh:

#!/bin/sh
(sleep 5 && /home/pi/consumo.php) &
(sleep 10 && /home/pi/consumo.php) &
(sleep 15 && /home/pi/consumo.php) &
(sleep 20 && /home/pi/consumo.php) &
(sleep 25 && /home/pi/consumo.php) &
(sleep 30 && /home/pi/consumo.php) &
(sleep 35 && /home/pi/consumo.php) &
(sleep 40 && /home/pi/consumo.php) &
(sleep 45 && /home/pi/consumo.php) &
(sleep 50 && /home/pi/consumo.php) &
(sleep 55 && /home/pi/consumo.php) &
(sleep 60 && /home/pi/consumo.php)

Lo admito: La elegancia programando no es lo mío, no me acordaba muy bien cómo eran los parámetros en Bash y prefería invertir el tiempo en esta entrada, que en dejarlo todo óptimo J

Finalmente vamos a poner este script con una línea en /etc/crontab:

* * * * * root /home/pi/plug.sh

Y ya debería funcionar cada 5 segundos, almacenando los datos de consumo en esos intervalos de tiempo.

Por último y para poner la guinda del pastel, si instalamos el servidor web Apache o LightHTTP como indicaba antes, podríamos tener un básico panel de control en PHP para saber la información que nos reporta esta base de datos (por ejemplo en /var/www/reportes.php)

<?php
class MiBD extends SQLite3
{
function __construct() { $this->open('/var/www/razberry.db'); }
}
$bd = new MiBD();
$resultado = $bd->query("SELECT AVG(valor),COUNT(valor) FROM plug WHERE (fecha > datetime('now','-24 hours')) AND (fecha < datetime('now')) AND (disp = 1)");
$res = $resultado->fetchArray();
$kwh = 0.162; // El coste el KWH de vuestra compañía de Luz
echo "Potencia Media en las ultimas 24 horas: ".$res[0]." W";
echo "<br/> Numero Registros: ".$res[1];
$coste = $res[0]/1000 * $kwh * 24 * 30;
echo "<br/> Coste Mensual: ".$coste." euros";
if (!function_exists('curl_init')){
die('Sorry cURL is not installed!');
}
$url = "http://ip_de_raspberry:8083/ZWaveAPI/Run/devices[2].instances[0].commandClasses[49].data[4].val.value";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$watios = curl_exec($ch);
echo "<br/> Consumo Actual: ".$watios." W";
?>

Y ahora me entero que mi emisor térmico efectivamente, no gasta tanto como creía:

Potencia Media en las últimas 24 horas: 150.13031858033 W
Numero Registros: 17273
Coste Mensual: 17.51120035921 euros
Consumo Actual: 282.6000128 W

Espero que os sirva de provecho esta guía para tener un pequeño Z-Wave casero. En un futuro, intentare adquirir algún producto adicional Z-Wave (un sensor de movimiento y una alarma por ejemplo), y planteare “fusionar” el mundo de la Domotica con Asterisk

 

raspberry pi domotica razberry z-wave

Domotica, Asterisk, Smart Metering y el Internet de las Cosas

Dado que este blog está cogiendo ciertos tintes de orientación del Sistema Asterisk, para entornos caseros o en el mejor de os casos, las pequeñas y medianas empresas, he pensado que sería bastante interesante empezar a introducir terceras aplicaciones relacionadas al mundo de la domotica, automatización de sistemas en casa (y en la oficina), y todo gestionado más allá de la tecnología software convencional como podrían ser las aplicaciones de los Smartphones y los entornos web.

domotica asterisk

Todo mi interés ha surgido a raíz del Tarifazo eléctrico acontecido recientemente en España, y el incremento de la factura de la luz en un porcentaje significativo (Sumado a los altos consumos de Inverno relativos al uso de sistemas de calefacción). Esto me ha llevado a investigar acerca de alguna posible opción domotica para controlar el consumo eléctrico con los populares Smart Meters (medidores Inteligentes de consumo). A esta práctica se le llama “Smart Metering” y en el entorno Demótico está totalmente en Auge.

Soluciones de Smart Metering para nuestro futuro sistema de Domotica

Después de revisar miles de opciones bastante costosas como IPDomo Energy Socket Meter, uno de los pocos dispositivos capaz de medir el consumo de un dispositivo en concreto y enviar la información vía Wifi (a un precio excesivo si cabe >180 euros), y la alternativa, control desde el Cuadro Eléctrico del consumo integral del domicilio, con E2 Efergy, empecé a tantear otras opciones basadas en protocolos propietarios de comunicación tales como la solución de ClienSol, EnviR, unido al módulo de conexión a internet, más un Enchufe con Sensor Inalámbrico por un total de cerca de 180 euros también, siendo toda la comunicación propietaria, y con montones de dispositivos de por medio).

En este momento descubrí los protocolos de comunicación “Inalámbricos” para la domotica (que hasta la fecha solo conocía los cableados como X10), y se presentó ante mí una de las apuestas fuertes, Zigbee, con el sistema Enistic Single Socket Smart Meter, que también tenía un alto coste (módulos más recibidor, etc…). Este fue el momento que estaba a punto de desechar la idea, porque consideraba que montar soluciones de estas características eran excesivamente costosas. Las aplicaciones con sistemas “Open Source” como Arduino eran totalmente rudimentarias, y muy poco fiables, lo que hizo en mí que las desechase prácticamente desde los inicios.

Pero de pronto me topé con una presentación del último evento Voip2Day 2013 sobre domotica, al que no pude Asistir, de Alberto Sagredo:

En esta presentación curiosamente, hace referencia a Z-Wave como otro estándar de comunicaciones para domotica, el cual está siendo ampliamente aceptado, y dispone de una cantidad de dispositivos increíblemente grande. Y concrétamente hubieron dos dispositivos que me llamaron especialmente la atención: Fibaro Wall Plug y RazBerry, y concrétamente este último porque se considera una placa para Raspberry Pi que permitiría una integración con un sistema como Asterisk en el mismo dispositivo y servir como servidor de comunicación para la intercomunicación con este dispositivo de Z-Wave.ME

De momento he realizado el pedido de estos dos dispositivos de domotica para empezar a probarlos. Tal y como ha hecho Alberto Sagredo en su presentación (que en su caso aplica los casos de uso entre Asterisk y un Controlador Z-Wave de la marca Zipato el modelo ZipaBox cuyo coste de 200 euros no es desdeñable, dentro de la franja de otros controladores Entry-Level como Vera Lite Smart Home Controller

Asterisk con Websockets para WebRTC y probando SIPML5

Volviendo a la carga con Artículos sobre Asterisk, voy a explicar algo que aunque ya está algo visto, ha sido parte de mi experiencia y como viendo haciendo hasta ahora intento explicarlo con el mayor número de detalles

Hay que considerar que en este momento estoy trabajando con la versión CERT de Asterisk concretamente la versión 11.6-cert1

webrtc asterisk

Preparando la instalación del Sistema Asterisk para WebRTC

En primer lugar, sería conveniente tener soporte para el códec OPUS que es una de las claves que WebRTC utilizan de forma nativa y quizá sea de las principales ventajas de su uso.

Si no tenemos autoconf necesitamos instalarlo y también hará falta libtool y pkg-config

# apt-get install autoconf libtool pkg-config

ATENCIÓN (Con Asterisk  >11.6) si compilamos con soporte OPUS habrá un problema de AUDIO (Issue en Git de Meetecho: https://github.com/meetecho/asterisk-opus/issues/6). Por eso este paso de instalación de Opus en este tipo de versiones, seria conveniente saltárselo de momento a partir de aquí:

Para ello lo podemos descargar desde el repositorio GIT de este proyecto. Tenemos que descargar este fichero en el directorio raíz donde esta el código de Asterisk listo para ser compilado.

#wget https://raw.github.com/meetecho/asterisk-opus/master/asterisk_opus+vp8.diff

Desde ahí lanzamos el parche

# patch -p1 -u < asterisk_opus+vp8.diff

Y a continuación preparamos el sistema para que pueda instalarse el códec OPUS:

# ./bootstrap.sh

En mi caso, trabajando con Ubuntu Server 12.04, me hace falta instalar la librería Opus en el sistema, que no viene en los repositorios de Ubuntu por defecto:

# apt-get install python-software-properties
# add-apt-repository ppa:ubuntu-sdk-team/ppa
# apt-get update
# apt-get install libopus-dev

Después de instalar el códec OPUS pasamos a instalar el resto de las dependencias para su funcionamiento

También nos hará falta la librería libsrtp0-dev para gestionar la encriptación de las conexiones WebRTC y las librerias de Universally Unique Identifier, uuid-dev (este último es específico la versión 11 de Asterisk y su no instalación provocaría problemas en la comunicación con ICE, y aunque la llamada entraría en el sistema, no se escucharía nada por una cuestión de RTP) . Podemos instalarlas directamente desde los repositorios del sistema:

# apt-get install libsrtp0-dev libsrtp0 uuid-dev

Con todo preparado realizamos la instalación de Asterisk

# ./configure --with-crypto --with-ssl --with-srtp=/usr/local/lib

Finalmente seleccionamos el códec Opus y Formato VP8 con make menuselect (Codec Translators -> códec_opus y Format Interpreters -> format_vp8)

Por otro lado, para instalar nuestro sistema websockets en Asterisk primero deberemos instalar el Recurso HTTP Websocket. Esto se realiza durante la instalación de Asterisk (make menuselect) en la sección Resource Modules, y cuyo nombre es res_http_websocket

También se recomienda por cuestiones de calidad, seleccionar los paquetes musicales tanto los mensajes de Asterisk como los de Music On Hold en formato SLN16 (CORE-SOUNDS-ES-SLN16, MOH-OPSOUND-SLN16 y EXTRA-SOUNDS-EN-SLN16)

Y ya podemos compilar Asterisk con todo el soporte necesario

# make && make install

Configurando Asterisk y Websockets

A partir de aquí ya tenemos el sistema preparado para ser configurado simplemente. En primer lugar configurador el servidor HTTP de Asterisk desde el fichero http.conf

[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088

A continuación pasamos a configurar el soporte ICE y STUN en el fichero RTP.conf para ello añadimos las líneas dentro de la etiqueta [general]

icesupport=true
stunaddr=stun.l.google.com:19302

Finalmente pasamos a configurar un peer SIP para que soporte la comunicación con WebSockets. En el fichero sip.conf dentro de la etiqueta [general]:

allowguest=no
udpbindaddr=0.0.0.0:5060

Y creamos una extensión con los siguientes parámetros

[extension1]
secret=miclavesecreta
transport=udp,wss,ws
encryption=yes
avpf=yes
icesupport=yes
directmedia=no
host=dynamic
nat=force_rport,comedia
qualify=yes // opcional
type=friend
context=phones

Con todo esto solo necesitaremos configurar en nuestro servidor Web un softphone basado en WebRTC y que soporte WebSockets (esto es opcional, si tenemos publicado el servidor SIP el webphone RTC se conectaría directamente, los websockets serían utiles en caso que definieramos en el sip.conf un nombre al dominio (con la propiedad realm) y conectáramos a este realm a traves de una conexión con Websockets (otra de las claves principales de WebRTC junto al Codec OPUS). Por ejemplo,supongamos la dirección pública de nuestro servidor es 123.123.123.123 y hemos abierto el puerto 8088 (del servidor HTTP de Asterisk para habilitar los Websockets). Configuramos en el fichero sip.conf,

[general]
realm=10000horas.com

Ahora en el softphone configuramos (por ejemplo SIPML5, aunque pongo otras opciones más adelante):

Private Entity: la extensión usada, en este caso extension1
Publc Entity: sip:[email protected]
Password: la_password_de_la_extension
Realm: 10000horas.com

Y en el apartado “Expert” debemos configurar la dirección a la que apunta el Websocket. Usando comunicación Websockets sin encriptar:

Websocket Server URL: ws://123.123.123.123:8088/ws

Así estableceríamos la conexión en vez de directamente al servidor SIP, lo haríamos gracias al servidor WebSocket, lo que es bastante provechoso y podríamos llegar a incrementar la seguridad del sistema (considerando que tener el Puerto 5060 a libre albedrío es peligroso, aunque no todos opinan lo mismo)

Disponemos de varias opciones entre las más populares SIPML5 y JsSIP. De todas formas si tenemos el servidor delante de un firewall o hemos gestionado los puertos correspondientes podríamos hacer una prueba desde cada uno de los sistemas:

SIPML5: http://sipml5.org/call.htm
JsSIP: http://tryit.jssip.net/

Espero que os haya servido, os recomiendo el cliente de escritorio Phoner Lite (http://phonerlite.de/index_en.htm) si queréis hacer pruebas ya que es de los pocos Softphones que dispone del códec OPUS por defecto.

Asterisk en 10000 Horas vuelve al mercado

Despues de algo mas de un año en total inactividad, motivado en parte por serios desajustes en el blog y otros avatares que han impedido poder desarrollar la actividad normal del mismo (ademas de la creación de un blog algo mas corporativo, Voipelia donde se tratan temas mas relativos a la VoIP en general, y menos especificos a Asterisk en concreto), he vuelto a poner en funcionamiento al 100% el blog, con un nuevo diseño (quiza sea temporal) entre otras mejoras que ire implementando en los próximos días.

presente-futuro-300x194

Hay que reconocer que a estas alturas el blog tiene contenido sobre Asterisk de buena calidad, y tengo desde todo este tiempo, tres artículos en el tintero que me gustaría poner en practica y describir con mucho detalle para todos aquellos que pudieran estar interesados en utilizarlos.

Tambien he dejado algo inactivo el WIKI sobre Asterisk (WIKI Asterisk) que al final tampoco pude presentarlo al Concurso Universitario de Software Libre (CUSL), como anunciaba en al anterior entrada, por motivos principalmente de tiempo.

Novedades en Asterisk y otros avatares

Como novedades hay que destacar la salida de Asterisk 12, y todas las novedades de Asterisk 11 que en este Blog comente también en su día y ofrecian bastante potencial para poder desarrollar nuevos “inventos” de utilidad para aplicaciones muy concretas relacionadas a la VoIP principalmente. Como Voipelia tampoco se encuentra especialmente activa, quizá me plantee fusionar los dos blogs e incorporar a todos los colaboradores de dicho Blog a este para que sea mucho más activo dentro de lo posible. Tras todos estos propósitos para el 2014 con respecto a este blog, me gustaría que si os gustaría que tratara algún tema en concreto, os pongáis en contacto conmigo (o escribáis algún comentario aquí), y tratare de sacarlo en adelante lo antes posible.

Asterisk WIKI en el CUSL

logo

Como el año pasado WIKIAsterisk no pudo acceder al Concurso Universitario de Software Libre porque este había acabado cuando el proyecto empezó, he decidido acceder al concurso de este año. Además como en la actualidad me encuentro cursando un Master Oficial en la Universidad de Sevilla, pues tengo permitido el acceso a dicho Concurso.

http://www.concursosoftwarelibre.org

Con el acceso, tengo intención de agregar nuevos elementos a la WIKIAsterisk, tenía dos proyectos en mente: Uno relacionado a Asterisk SCF y otro relacionado al desarrollo orientado a Asterisk. La verdad es que no me encuentro muy ducho en ninguno de estos dos campos, pero como Asterisk SCF fue abandonado hace relativamente poco, pues el único tema que me queda pendiente es el de desarrollo. Me gustaría aprovechar esta actualización de la WIKI para ahondar en mis conocimientos sobre el sistema Asterisk, y acceder a un mundo hasta la fecha totalmente desconocido para mi.

En estos momentos estoy tanteando por donde empezar. Hace poco tenía intención de publicar un mensaje relativo a chan_mobile mostrando como configure mi movil Android con mi maquina Asterisk para cursar llamadas, pero este post no llegó a ver la luz por una sencilla razón: Nunca me llego a funcionar. Teóricamente chan_mobile ha estado ofreciendo una resistencia al sistema desde la versión 1.8 de Asterisk, pero para mi resulta bastante incierto si el problema era raíz del modulo Bluetooth, de la versión Android (4.1) o simplemente de la versión del máquina Asterisk. Quizá un primer acercamiento al mundo de la programación de Asterisk sería la posibilidad ahondar en la programación de este módulo de Asterisk, de todas formas si alguien que lea este blog y tenga experiencia en este tema desea ser mi Mentor le estaré ampliamente agradecido :)

Por aquí pasa el proceso de aprendizaje, como el nombre del blog indica: 10000 Horas hacen falta para adquirir la Maestría en algo. Y ya vamos por el buen camino de alcanzarlas en lo relativo a Asterisk.

Seguiré informando sobre futuras novedades sobre esta nueva aventura, y sobre lo relativo a este Concurso.

Asterisk 11: Nueva version LTS

 

Finalmente, tras pasar un par de años desde el lanzamiento de la ultima version LTS de Asterisk (la version 1.8), acaba de salir (sin anunciarse) la version final de Asterisk 11.

En los proximos meses es probable que salga la version Asterisk Certified dentro de Asterisk 11, asi que de momento, no creo que sea buena idea actualizarse a esta version, especialmente como suele decirse en estos casos, dentro de los entornos de produccion.

Pero Asterisk 11 trae una serie de mejoras que merece la pena comentar:

  1. A partir de la version 10 de Asterisk, aunque ya existia, se pretendia estandarizar el uso de la nueva version para Conferencias ConfBridge ante un MeetMe ya obsoleto. Parece que ya la version 11 es un buen momento para empezar a utilizar esta aplicacion y dar de lado la antigua. Recordar que ConfBridge tiene como principal ventaja, que no necesita una fuente de sincronizacion, es decir, que no necesitamos DAHDI para hacerla funcionar.
  2. Resurge la compatibilidad con Google Talk y Jingle de la mano de un Channel Driver llamado chan_motif.
  3. Se ha mejorado al maximo la compatibilidad con Telefonos IP UNIStim antiguamente pertenecientes a Nortel (ahora Avaya). ¿Que ventaja parece ser que tienen estos telefonos? Que segun Digium pueden encontrarse a precios muy baratos (yo no los he visto, si conoceis alguno, comentadlo)
  4. Esto no es nuevo de la version 11 sino de la 10, pero AstDB ya no es de tipo Berkeley DB sino ahora es SQLite, no afecta a efectos practicos pero siempre es bueno saberlo
  5. Para los que utilizan el protocolo XMPP (Jabber para los amigos) en presencia, considerar que muere el Recurso res_jabber y ahora se llama res_xmpp, a efectos, al ser un recurso da igual porque encima es retrocompatible no hay que modificar nada para que todo siga funcionando tal como estaba antes, pero tambien es bueno saberlo
  6. Ahora es mas facil seguir las llamadas dentro de la CLI y los logs porque se ha añadido un parametro que es el ID de Llamada (que no el Caller ID). Con este ID de llamada, si hay varias llamadas entrantes simultaneamente, podremos seguir los pasos de cada llamada, aunque se solapen con otras. Muy practico en situaciones donde hay decenas o cientos de llamadas simultaneas.
  7. Parece que la compatibilidad con IPv6 sigue avanzando, y ahora lo soportan muchos mas modulos de Asterisk, como Asterisk Manager Interface (AMI) y Asterisk Gateway Interface (AGI).
  8. Tambien va a haber soporte para ICE dentro de la configuracion SIP. Esto creo que es fundamental considerando que las comunicaciones SIP siguen siendo el principal caballo de batalla de Asterisk.
  9. Ya supuestamente, hay compatibilidad con websockets desde Asterisk. Necesito probarlo para creerlo, porque definitivamente esto va a ser un paso adelante cuando WebRTC se estandarice en los navegadores por completo
  10. Como el proyecto OpenAIS fue abandonado definitivamente (sistema de Alta Disponibilidad y Clustering para servidores Linux), CoroSync ha tomado el relevo. Eso significa que el Recurso OpenAIS (res_ais) pasa a llamarse res_corosync. Esto es un sistema poco comentado a nivel de Alta Disponibilidad entre la comunidad Asterisk, pero creo que merece la pena ser profundizado un poco en un futuro.

Recordar un tema importante acerca del nuevo sistema de Versiones de Asterisk que ha sufrido grandes cambios en estos dos ultimos años. La politica de actualizaciones de Digium se basa en dos niveles:

  •  Primero se saca una version “Estandar”, que en cierto sentido, no suele ser recomendada para entornos de alta produccion. Podria considerarse una version “Beta” de la versión que vendra a continuacion. Hasta hace poco coincidian estas versiones con numeros Impares (Asterisk 1.5, Asterisk 1.7…) pero como Asterisk ha dado un salto para eliminar el 1 de la version, y pasar directamene al segundo digito, pues de ahora en adelante coincidira con las versiones pares (Asterisk 10, Asterisk 12, Asterisk 14…). Se ve que esta de moda que el software haga referencia a Versiones con un numero Alto (vease Chrome y Ubuntu, seguido de Firefox que ha hecho como 5 versiones en 2 años de un golpe).
  •  A partir de cada Version Estandar, se va forjando una Version LTS, que a partir de ahora ira en numeros impares (Asterisk 11, Asterisk 13…) cuando antiguamente eran las versiones pares (Asterisk 1.4, Asterisk 1.6, Asterisk 1.8). Desde Asterisk 1.8 se anuncio que dentro de una subversion bastante estable del sistema, saldra un “Branch” que no mejorara en funcionalidad, sino exclusivamente en estabilidad y segurida. A esta version se le llamara Asterisk Certified.

Yo desde aqui, recomiendo que para entornos de produccion os quedeis con una version Asterisk Certified siempre. Es donde Digium va a poner mayor enfoque especialmente a nivel de estabilidad, y ademas para aquellos clientes que tengan contratos con acuerdos de nivel de servicio (SLA) va a tener la ventaja que esta version va a ser la soportada por los mismos (exclusivamente en las relaciones con Digium), con lo cual muy probablemente la mayor parte de los redistribuidores de Asterisk tambien se acojan a este sistema de implementacion.

Finalmente comentar que tengo un par de articulos en borrador, muy interesantes pendientes de publicar, pero en estos ultimos meses a raiz de lanzar WIKIAsterisk me he encontrado bastante ocupado y no he tenido tiempo a dedicar a la parte “online” de Asterisk todo el tiempo que me hubiera gustado.

Lanzamiento de WIKI Asterisk

Seguramente muchos de los lectores de este Blog sobre Asterisk, hayan notado mi ausencia en los últimos meses. Evidentemente esto es básicamente porque no escribo desde hace casí 6. Podría parecer como en aquel post que por cuestiones personales, me encontré en la necesidad de dejar de lado el mundo de Asterisk para ocuparme de otros asuntos.

Pero justamente esto no ha sido así en este caso, ya que he estado centrado en Asterisk, quizá más que nunca desde que empece.

Hoy quería hacer este mensaje, para dar la bienvenida a mi nueva página dedicada exclusivamente a Asterisk, en formato WIKI, llamada WIKIAsterisk: http://www.wikiasterisk.com

Mi intención es dar difusión al sistema Asterisk, en un soporte bajo el idioma Español, y que mejor momento que al inicio de la Eurocopa, donde es el único momento cada dos años, todo el mundo se exalta con la bandera Española. Realmente, la intención también es dar cobertura a los países hispanohablantes que también son seguidores de este Blog sobre Asterisk por afinidad de idioma.

De momento la WIKI de Asterisk, aun considerándose como una herramienta colaborativa destinada a ser ampliada abiertamente por la comunidad, permanecerá cerrada seguramente hasta el 1 de Julio, momento en el que empezarán a aceptarse solicitudes de edición.

Es posible que encontréis muchos errores, dado que es una versión llamémosla Release Candidate

Estoy seguro que con el tiempo servirá de referencia por encima de las WIKIs oficiales, dado que no todo el mundo maneja el inglés lo suficientemente bien para poder entender mucho de los conceptos técnicos que se tratan en el mundo de Asterisk. Además hay que reconocer que leer algo en tu idioma natal, supone una asimilación de conceptos mucho más rápida, y la dedicación que requerimos es muchísimo inferior.

Todo sea, como el lema de este Blog de Asterisk, para reducir la curva de aprendizaje. Cualquier cuestión que os surja acerca de esta nueva iniciativa, tenéis mis datos de contacto dentro de la misma web.

También “extraoficialmente” tengo que decir, que uno de los motivos por los cuales se me ocurrió adicionalmente realizar este proyecto que llevaba meses queriendo poner en marcha, es debido a que tengo la intención de presentarme al examen de Asterisk oficial, dCAP el 21 de Septiembre de 2012, y con ello tengo la pretensión de intentar cubrir a modo teórico y práctico todo lo que es posible que caiga en dicho examen, para que sirva como una referencia para todo aquel que quisiera presentarse en un futuro.

Larga vida a Asterisk

Asterisk. Revisando Opciones de Text To Speech

Asterisk: Tenia programado escribir en dos partes, sobre ASR y ahora sobre TTS (serian las dos cara de la moneda)

Siguiendo con la linea de programacion con AGI, ahora se me ocurre la opcion de dotar de un servicio de Text To Speech a nuestro Asterisk, del nivel AT&T Natural Voices utilizando el mismo sistema que aplicamos con nuestro sistema ASR en el anterior mensaje (como es un servicio con un modelo ASP evidentemente no tendremos problemas de licencias siempre y cuando ese sistema permanezca en activo). Lo malo, claro esta, que si ese servicio se modifica (la URL por ejemplo), nos quedamos sin “negocio”. Por eso que es conveniente si el sistema lo utilizamos en produccion y somos capaces de rentabilizarlo, pasar a un sistema de TTS local en nuestro sistema.

Para mantenernos en una linea open source como Asterisk, tenemos la opcion de Festival, el problema es que es de muy baja calidad comparado a soluciones de pago o la que voy a proponer aqui, a traves del TTS de Google

Texto a Voz con Google TTS

Vamos manos a la obra partiendo de la base AGI voy a obviar que se hicieron todos los pasos del mensaje anterior para instalar lo necesario (php-curl, y php-agi lo mas importante), hacemos lo siguiente:

Primero vamos a descargar un sistema para convertir de MP3 a WAV.

# aptitude install lame

Vamos a crear un Script PHP en /var/lib/asterisk/agi-bin/ podemos llamarlo por ejemplo asterisk-tts.php:


#!/usr/bin/php -q
<?php
require_once('phpagi-2.20/phpagi.php');
$agi = new AGI();

# Necesitamos pasarle la Cadena de Texto desde el Asterisk, y la recogemos con esta variable.
$traduccion = $argv[1];

# Aqui descargamos el fichero Mp3 haciendo pensar a Google que somos un Navegador
shell_exec("wget --header='User-Agent:Mozilla/4.0' 'http://translate.google.com/translate_tts?tl=es&q=".$traduccion."' -O /var/lib/asterisk/sounds/google-tts.mp3");
# Y convertimos el fichero con "lame" a wav que es reconocible por Asterisk
shell_exec("lame -h --decode /var/lib/asterisk/sounds/google-tts.mp3 /var/lib/asterisk/sounds/google-tts.wav");
$retString = "Fin de la conversion";
$agi->verbose($retString);
?>

Finalmente creamos una extension en nuestro DialPlan de Asterisk para que haga esta “gestion”:


exten => 2000,1,Answer()
same => n,Set(TTSVAR = "Lo que queramos convertir")
same => n,AGI(asterisk-tts.php,${TTSVAR})
same => n,Playback(google-tts)
same => n,Hangup()

Y ya esta, recargamos el dialplan de Asterisk como siempre, y marcando la extension 2000 oiremos con una voz muy sensual: “Lo que queramos convertir” … o algo asi :)

Como veis la dificultad de implantacion es nula, y eso es lo que mas me ha gustado de AGI, que no hace falta estar creando aplicaciones en C-Arcaico y recompilando el Asterisk con la app_c_arcaico y podemos tener una funcionalidad semejante (aunque no nativa y para los mas sibaritas, con menos rendimiento en terminos de picosegundos). Lo que tampoco tengo muy claro es que Google este feliz que esten utilizando su TTS masivamente, aunque estoy seguro que ya habra por ahi algun Call-Center que lo este haciendo. Si tienen experiencia me gustaria que me lo comentaran.

Texto a Voz con Festival TTS

Ahora os voy a explicar como hacer lo mismo, pero con el sistema TTS Festival en local, que os comente antes, y asi podeis comparar que os gusta mas:

Festival TTS digamos que fue desarrollado por una universidad e incorporado nativamente en Asterisk, asi que eso simplifica bastante las cosas ya que existe una Aplicacion especifica para el tratamiento de Texto a Voz directamente para el dial Plan de Asterisk (el modulo app_festival.so). Primero tenemos que comprobar si lo tenemos preparado.

Desde el CLI> module show like festival

Si aparece algo asi como app_festival.so y “1 modules loaded”, entonces ya lo tenemos, sino, nos toca recompilar Asterisk y en la parte de make menuselect tenemos que seleccionar el app_festival antes de hacer el “make && make install”

Ahora vamos a instalar festival

#aptitude install festival

Y ahora necesitamos voces en Español para Asterisk. Yo vivo en Andalucia ahora mismo, asi que barriendo para casa tenemos las que usa la junta de andalucia en la forja de Guadalinex:
http://forja.guadalinex.org/frs/?group_id=21

Vamos a descargar las de Silvia, para comparar el grado de sensualidad con respecto a Isabel de Google, todo sea por motivar a nuestros clientes varones.

# wget http://forja.guadalinex.org/frs/download.php/154/festvox-sflpc16k_1.0-1_all.deb
#dpkg -i  festvox-sflpc16k_1.0-1_all.deb
Y borramos el fichero de configuracion de festival que crea automaticamente, para poder utilizar mejor, el generico de Festival.
#rm /etc/festival.scm

La voz queda automaticamente instalada en la ruta:
/usr/share/festival/voices/spanish/JuntaDeAndalucia_es_sf_diphone

Ahora necesitamos modificar el archivo de configuracion de Festival por defecto ubicado en /usr/share/festival/festival.scm al final del fichero agregamos:


(set! voice_default 'voice_JuntaDeAndalucia_es_sf_diphone)
(define (tts_textasterisk string mode)
(let ((wholeutt (utt.synth (eval (list 'Utterance 'Text string)))))
(utt.wave.resample wholeutt 8000)
(utt.wave.rescale wholeutt 5)
(utt.send.wave.client wholeutt)))
(set! server_access_list '("localhost\\.localdomain" "localhost"))

Con esto, nos permitira por un lado utilizar la voz de Silvia y por otro lado arrancar el servidor Festival

Ahora necesitamos configurar el servidor Festival, bajamos los ficheros de desarrollo de festival
#aptitude install festival-dev

Y copiamos el fichero de autoarranque de festival a nuestro /etc/init.d para que arranque automaticamente el servidor cada vez que iniciemos nuestra maquina Asterisk:
#cp  /usr/share/doc/festival/examples/festival.init /etc/init.d/festival
#chmod +x /etc/init.d/festival

Antes de arrancar el servidor de Festival para Asterisk, necesitamos añadir una linea en /etc/default/festival:
RUN_FESTIVAL = yes

Y ahora si podemos arrancar el servidor Festival para Asterisk con exito:
/etc/init.d/festival start

Y para que arranque cada vez que iniciamos el sistema:
#ln -s /etc/init.d/festival /etc/rcS.d/S99festival

Ya esta todo casi listo, solo nos queda la parte mas facil, crear una extension en el DialPlan para ejectuar la aplicacion Festival
exten=> 3000,1,Answer()
same => n,Festival(Lo que queramos convertir)
same => n,Hangup()

Recargamos el dialplan de Asterisk como siempre y si marcamos la extension 3000, tendremos a Silvia dandonos el resultado.

Algunas cosas curiosas que he observado.
La version 1.0-1 de Guadalinex para Pedro parece que esta mal empaquetada. Instala sobre la version de Silvia (es_sf) en vez de (es_pa)
Se puede resolver de varias formas, una es, bajando las fuentes  (Archivos de desarrollo de la voz de Pedro) en el directorio correspondiente /usr/share/festival/voices/spanish/JuntaDeAndalucia_es_pa_diphone

Necesitamos desempaquetar tambien el .deb de Pedro con el comando “ar” (#ar x festvox-palpc16k_1.0-1_all.deb)
Y luego descomprimir data.tar.gz y a traves de la estructura de directorios llegar a …/usr/share/festival/voices/spanish/JuntaDeAndalucia_es_pa_diphone/group
Cambiamos el nombre al fichero que hay y lo copiamos a un nuevo directorio group dentro de nuestro directorio de Pedro antes creado
#mkdir /usr/share/festival/voices/spanish/JuntaDeAndalucia_es_pa_diphone/group
#mv  sflpc16k.group /usr/share/festival/voices/spanish/JuntaDeAndalucia_es_pa_diphone/group/palpc16k.group
O lo ideal si a  alguien le interesa que arregle ese fichero deb, no voy a ser yo, porque no me gusta demasiado.

Si tuviera que elegir personalmente un fichero para Festival en Español para Asterisk, eligiria de hecho, el fichero por defecto de festvox en español (el_diphone) que es el que mejor se entiende para mi gusto, aunque es voz masculina asi que no podriamos comparar bien para este ejemplo.
Se puede descargar y configurar siguendo los mismos pasos que antes, pero en el idioma por defecto poner “voice_el_diphone”
# aptitude install festvox-ellpc11k

Ahora puestos a comparar entre Festival TTS y Google TTS, creo que no hay color, pero para gustos los colores. Espero vuestras experiencias en el mundo del TTS.

Asterisk @ 10000 Horas

Un AGI Legendario: Publicacion en Twitter mediante ASR

Para muchos, hoy es un dia de fiesta en España, pero para mi, es mi, es como el dia oficial de Asterisk, y me siento especialmente inspirado. Y aprovechando el momento estuve planteando alguna aplicacion curiosa que hacer con AGI.

Echando la mirada atras, durante el penultimo dia del Asterisk Advanced, tuvimos una breve introduccion al AGI (Asterisk Gateway Interface), y porque no decirlo, a mi me resulto de lo mas interesante del curso. Siempre habia sabido que existia tanto AMI como AGI pero hasta ese momento no me “atrevi” a profundizar, sea por desconocimiento, y por complejidad aparente.

De hecho, concretamente en ese mensaje del Dia 4 del curso, no publique nada acerca de estos interfaces de Asterisk, porque me resultaban lo suficientemente interesantes e importantes como para minimo dedicarle uno o varios mensajes a los mismos.

Y aqui va el primero. Durante el curso, la practica basicamente se trataba, de llamando a una extension, esta ejecutaba un script PHP a traves de AGI y se publicaba un tweet generico con cierta informacion en un usuario especifico para el curso (por interes todos van aqui: http://twitter.com/#!/agilabtest)

Realmente la practica lo daba todo bastante “masticado”, los scripts hechos, y exactamente lo que era necesario para que funcionara, y lo que habia que modificar en el DialPlan.

Pero ahora, aprovechando esta idea, se me ocurrio ir un paso mas alla y ademas de poder explicarlo todo un poco mas en detalle, ampliar la funcionalidad a algo muy interesante: Poder escribir un tweet en nuestro Twitter, llamando a traves de una extension, y diciendo lo que queremos escribir, con un sistema de Automatic Speech Recognition, ASR, o Reconocimiento de Voz Automatico, y lo mejor de todo, sin coste alguno (¿es posible?). Hoy me quede con la cita “Everything is possible, even impossible is: I’m possible y tambien aporto su granito.

En primer lugar vamos a “preparar” el sistema con algunos componentes basicos.

Por un lado necesitamos una libreria para poder trabajar con PHP a traves de AGI, llamada PHP-AGI. Es posible su descarga desde aqui:
http://phpagi.sourceforge.net/

Para este ejemplo yo recomiendo la version 2.2X puesto que si en un futuro saliera una version superior es posible que el script aqui realizado ya dejara de funcionar
La descargamos  http://sourceforge.net/projects/phpagi/files/phpagi/2.20/phpagi-2.20.tgz/download

Y descomprimimos aqui: /var/lib/asterisk/agi-bin/
#mv ./phpagi-2.20.tgz /var/lib/asteirsk/agi-bin/
#cd /var/lib/asteirsk/agi-bin/
#tar -xvf phpagi-2.20.tgz

Ahora por otro lado necesitamos un script en php escificamente creado para “operar” con Twitter,  (de hecho es generico, serviria incluso para desarrollar nuestras propias aplicaciones en php en relacion a Twitter).  Aqui hay varias librerias para Twitter: https://dev.twitter.com/docs/twitter-libraries#php .

Pero la que nos interesa para este caso es la siguiente: http://classes.verkoyen.eu/twitter_oauth

La descargamos:

#mkdir twitter-oauth
#cd twitter-ouath
#wget https://github.com/tijsverkoyen/TwitterOAuth/zipball/2.1.2 -O twitter-oauth.zip
#unzip twitter-oauth.zip
Nos crea un directorio con un nombre sacado de GitHub asi que entramos en ese directorio
# cd  <directorio-recien-creado>
# cp twitter.php ../../twitter.php

Asi ya tenemos el script este en nuestro directorio AGI-BIN

Estos scripts utilizan PHP-CURL, asi que, si no lo tenemos instalado es un buen momento para hacerlo:
#aptitude install php5-curl

Tambien nos va a hacer falta un conversor de WAV a FLAC para el Reconocimiento de Voz Automatico. En este caso, instalamos SOX si es que no lo tenemos ya.
#aptitude install sox

Antes de crear el script, necesitamos algo muy importante. Las claves del API de Twitter para el desarrollo de aplicaciones. De hecho necesitamos crear y autorizar una aplicacion en Twitter que va a ser con la que va a operar nuestro Script. Para ello entramos en:
https://dev.twitter.com/user/login?destination=home

Accedemos con nuestra cuenta de Twitter. Le damos a “Create an app”. Ponemos un nombre, una descripcion y una web, si no teneis web, pues poned http://www.10000horas.com para promocionarla !
Despues creamos la aplicacion. Ya en la aplicacion nos vamos a “Settings” y tenemos que picar la opcion: “Read, Write and Access direct messages”. Considerad que vamos a escribir directamente en nuestro tweeter por tanto es fundamental que este permiso este “activado”.

Finalmente necesitamos todas las claves para el script a continuacion y apuntarlas. Son las siguientes
1. Consumer key
2. Consumer secret
Abajo picamos en “Create my access Token” y apareceran dos claves mas:
3. Access token
4. Access token secret
Fijaros que abajo del todo ponga Access Level: Read, write, and direct messages, si pone otra cosa, teneis que fijar el tipo de acceso como comente antes, y volver a recrear las claves.

Y ahora nos toca crear dentro de AGI-BIN el script que vamos a ejecutar desde la Aplicacion AGI en el Dialplan

En este caso creamos un fichero llamamosle por ejemplo agitwitter.php, con el siguiente contenido (gran parte esta extraido del contenido del script ofrecido en las practicas del Asterisk Advanced, por eso hemos utilizado el script Twitter-Oauth de Tijs Verkonyen, en vez de cualquier otro, una cuestion de ahorro de tiempo).


#!/usr/bin/php -q

<?php

# Aqui cargamos el script twitter.php y el phpagi que descargamos antes.
require_once('twitter.php');
require_once('phpagi-2.20/phpagi.php');

# Creamos un nuevo objeto tipo AGI 
$agi = new AGI();
$agi->answer();

# Aqui ponemos las credeciales que obtuvimos antes, en el mismo orden
# Estas que aparecen aqui son las de un usuario que cree de pruebas http://twitter.com/#!/pruebasadvanced
$consumerKey = 'xIpIGMm3kP610xh1sJVDCA';
$consumerSecret = 'vBT8eufZInFTPt02tGZeNdrb7o3YFDspCmtknS48JxY';
$accessToken = '414849063-IUB9SgA2fVr6vgk6zpYoJWAxwolGmlyA8qw361Z8';
$accessTokenSecret = 'ofo0kZrUTIXWJ1tul8zazifrNEhc0qTabzqHBADctvA';

# Aqui viene lo mejor del mensaje. Con estas lineas conseguimos un reconocimiento automatico de voz gracias a un servicio que pocos conocen
# y que ofrece el equipo de Google gratuitamente (al menos hasta lo que yo se).
# Creditos por ofrecerme este descubrimiento a http://www.ardumania.es

# Primero convertimos el fichero que generamos desde Asterisk a formato FLAC (que es el que admite Google)
shell_exec("sox  /var/lib/asterisk/sounds/twitter.wav /var/lib/asterisk/sounds/twitter.flac");

# Despues lanzamos una peticion a Google para que nos convierta el fichero FLAC en texto, nos devuelve una cadena de texto formato JSON
$linea = shell_exec("wget --post-file /var/lib/asterisk/sounds/twitter.flac --header='Content-Type: audio/x-flac; rate=8000' -O - 'http://www.google.com/speech-api/v1/recognize?lang=es_ES'");

# Convertimos esa cadena JSON gracias a PHP en un objeto directamente
$obj = json_decode($linea);

# Y conociendo la estructura exacta de ese objeto (contiene mucha mas informacion interesante, como la "calidad" de la conversion), sacamos el texto ya convertido
$tweet = $obj->{"hypotheses"}[0]->{"utterance"};

# Ya en adelante simplemente lo que hacemos es utilizando las funciones del script Twitter-Oauth publicamos en Twitter nustro Tweet
try

{
$t = new Twitter($consumerKey, $consumerSecret);
$t->setOAuthToken($accessToken);
$t->setOAuthTokenSecret($accessTokenSecret);

$retArray = $t->statusesUpdate($tweet);
$retString = "SUCCESS: Tweet id " . $retArray['id_str'] . " posted at " . $retArray['created_at'];
}
catch(Exception $e)
{
$retString = "FAILURE: " . $e->getMessage();
}

# Para terminar reportamos a Asterisk el resultado (si tenemos activada la opcion verbose en nuestro CLI podremos ver el mensaje de exito si salio bien la cosa
$randNum = rand(1000, 9999);

$retString .= ". ID " . $randNum;
$agi->verbose($retString);
$agi->hangup();

?>

Ahora una vez que tenemos el script PHP listo, solo nos falta editar nuestro DialPlan para ejecutarlo. En este caso he creado una extension minima para que podamos obtener el resultado que estamos buscando

exten => 1000,1,Answer()
same => n,Record(twitter.wav)
same => n,AGI(agitwitter.php)
same => n,Hangup()

Recargamos nuestro dialplan (CLI> dialplan reload) y listo!

Un tema muy importante para que todo esto funcione y que creo que a estas alturas sobra decir: ES FUNDAMENTAL TENER ACCESO A INTERNET EN NUESTRA MAQUINA ASTERISK

Esa es la unica “contrapartida” de poder tener un ASR gratuito y de maxima calidad… creo que en muchos casos es asumible. En otro caso tendremos que plantearnos otras alternativas de reconocimiento de voz automatico como por ejemplo Verbio recomendado por Avanzada 7 o LumenVox recomendado por Digium (que son de pago y nada baratos), o buscarnos la vida con CMUSphinx que es OpenSource y no esta mal (aunque  de momento es muy inferior tanto al ASR de Google y a los dos de pago).

Ahora desde nuestro telefono solo nos queda hacer esa llamada de cortesia a  la extension 1000, suena el tono de hablar, decimos lo que queramos publicar en nuestro tweet (sobra decir que cuanto mas claro hablemos mejor, y si decimos palabra a palabra mejor aun para mejorar el reconocimiento, aunque el ASR de Google para mi gusto es el mejor del mundo y es capaz incluso de reconocer las frase hecha sin demasiada vocalizacion con un amplio numero de aciertos). Despues de hablar pulsamos la Almohadilla (#) para guardar el fichero de Voz (twitter.wav) y finalmente esperamos a que Asterisk haga el resto.

Entramos en nuestro Twitter… y voila! Nuestro mensaje recien escrito (si todo fue bien, sino, como comente, recomiendo activar en el fichero /etc/asterisk/logger.conf para CLI (console =>) la posibilidad de verbose, asi podemos ver los resultados que nos devuelve el script PHP y si hay error, lo que captura el “catch” del script PHP).

Esta vez que con un solo mensaje he matado dos pajaros de un tiro: explicacion de una implementacion de ASR en Asterisk y el funcionamiento de AGI utilizando PHP (que hay que reconocer que a dia de hoy desde que salio PHP5 es el lenguaje de programacion interpretado que mas me gusta, aunque todo esto tambien se podria haber realizado en otros como Ruby On Rails o Python, si os fijasteis en la pagina de scripts para Twitter habia para varios lenguajes).

Y como siempre, y una vez mas, que cualquier comentario sera ampliamente bienvenido! Espero que les sea de provecho.

Montando un Sistema Asterisk Autonomo I

Durante el curso de Asterisk Advanced, una de las cuestiones que surgieron con los compañeros, era el tema de la “practicidad” eventual que podia surgir a la hora de decidir montar una interfaz grafica a pesar de que muchos hayan criticado, es el simple hecho que otorga un “sistema” para que manos inexpertas (bajo nuestra aprobacion y previamente formados), puedan tomar el control de nuestro Asterisk sin nuestra supervision constante.

Evidentemente surgen algunas inconveniencias, que son inevitables en este tipo de situaciones, pero en las manos adecuadas, pueden ser mas pros que contras (por ejemplo explicandole a un equipo tecnico o IT funcionalidades basicas de Asterisk como crear nuevas extensiones para poder cursar llamadas. De esto se trata la idea de montar un sistema Autonomo (al menos autonomamente de nuestra persona).

Un paso mas alla, viendo el sistema RealTime de Asterisk, se me ocurrio la -evidente- idea de crear una micro interfaz grafica (por ejemplo basada en web con PHP como sera el caso que exponga a continuacion), para gestionar esos aspectos de Asterisk especificos, y poder definitivamente, tomando esto como ejemplo generico, poder obviar todas esas interfaces graficas (ejemplo FreePBX) para siempre.

Lo que me planteo de ejemplo ahora: Activar RealTime para los “peers” SIP de nuestro Asterisk y crear la interfaz grafica web en PHP para Crear y Borrar estas extensiones (La funcion de editar seria Borrar y volver a crear para este ejemplo sencillo, aunque realmente no seria nada dificil de implementar)

Como ya comente en su momento en otro mensaje, el montaje de un sistema RealTime es verdaderamente secuencial, es mas ya lo hicimos en las practicas durante Asterisk Advanced en detalle.

En primer lugar, obviamente necesitamos tener instalado un sistema de gestion de bases de datos como MySQL, tambien un servidor web como Apache, y los modulos de PHP para el mismo. En este caso, como ya vimos antes, LAMP es lo ideal. Asi que ejecutamos tasksel y lo instalamos (LAMP Server, Ubuntu/Debian)

Tambien necesitamos las librerias de ODBC puesto que vamos a utilizarlas con Asterisk:

# aptitude install unixodbc libmyodbc

En segundo lugar, configuramos la base de datos y la tabla donde volcar los usuarios SIP:

- Creamos un fichero por ejemplo en /tmp/ llamado por ejemplo sip_buddies.sql con esta informacion (se puede encontrar mas informa acerca de la tabla asociada a los peers SIP  aqui). Atencion al ultimo campo que coloreo en Rojo. Muy importante que lo agreguéis manualmente para lo que vamos a tratar de hacer a continuacion

CREATE TABLE `sip_buddies` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(80) NOT NULL default ”,
`host` varchar(31) NOT NULL default ”,
`nat` varchar(5) NOT NULL default ‘no’,
`type` enum(‘user’,'peer’,'friend’) NOT NULL default ‘friend’,
`accountcode` varchar(20) default NULL,
`amaflags` varchar(13) default NULL,
`call-limit` smallint(5) unsigned default NULL,
`callgroup` varchar(10) default NULL,
`callerid` varchar(80) default NULL,
`cancallforward` char(3) default ‘yes’,
`canreinvite` char(3) default ‘yes’,
`context` varchar(80) default NULL,
`defaultip` varchar(15) default NULL,
`dtmfmode` varchar(7) default NULL,
`fromuser` varchar(80) default NULL,
`fromdomain` varchar(80) default NULL,
`insecure` varchar(4) default NULL,
`language` char(2) default NULL,
`mailbox` varchar(50) default NULL,
`md5secret` varchar(80) default NULL,
`deny` varchar(95) default NULL,
`permit` varchar(95) default NULL,
`mask` varchar(95) default NULL,
`musiconhold` varchar(100) default NULL,
`pickupgroup` varchar(10) default NULL,
`qualify` char(3) default NULL,
`regexten` varchar(80) default NULL,
`restrictcid` char(3) default NULL,
`rtptimeout` char(3) default NULL,
`rtpholdtimeout` char(3) default NULL,
`secret` varchar(80) default NULL,
`setvar` varchar(100) default NULL,
`disallow` varchar(100) default ‘all’,
`allow` varchar(100) default ‘g729;ilbc;gsm;ulaw;alaw’,
`fullcontact` varchar(80) NOT NULL default ”,
`ipaddr` varchar(15) NOT NULL default ”,
`port` smallint(5) unsigned NOT NULL default ’0′,
`regserver` varchar(100) default NULL,
`regseconds` int(11) NOT NULL default ’0′,
`lastms` int(11) NOT NULL default ’0′,
`username` varchar(80) NOT NULL default ”,
`defaultuser` varchar(80) NOT NULL default ”,
`subscribecontext` varchar(80) default NULL,
`useragent` varchar(20) default NULL,
`useradmin`  int(1) NOT NULL DEFAULT ’0′,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
KEY `name_2` (`name`)
) ENGINE=MyISAM ROW_FORMAT=DYNAMIC;

#mysql -p
Entramos con nuestra password
mysql> create database asterisk;
mysql> use asterisk;
mysql> source /tmp/sip_buddies.sql

En tercer lugar vamos a configurar los ficheros basicos de Asterisk para poder trabajar con el conector ODBC

/etc/asterisk/extconfig.conf

[settings]
sippeers => odbc,asterisk ,sip_buddies

/etc/asterisk/res_odbc.conf

[asterisk]
enabled => yes
pre-connect => yes
dsn => asterisk
username => root
password => (el password que le pusimos al usuario de la base de datos mysql root durante la configuracion de LAMP)

/etc/odbc.ini

[asterisk]
Description = ODBC para MySQL
Driver = MySQL
Server = localhost
Database = asterisk
Socket = /var/run/mysqld/mysqld.sock

/etc/odbcinst.ini

[MySQL]
Description = MySQL ODBC MyODBC Driver
Driver = /usr/lib/odbc/libmyodbc.so
Setup = /usr/lib/odbc/libodbcmyS.so

Con esto vamos al CLI de Asterisk
# asterisk -r
CLI> odbc show

Y si vemos “Connected: Yes” entonces ya esta preparado

En cuarto lugar vamos a configurar los usuarios SIP:

Para ello creamos un fichero temporal por ejemplo /tmp/usuarios_sip_buddies.sql con la siguiente info:

INSERT INTO sip_buddies (`name`, `host`, `nat`, `type`, `cancallforward`, `canreinvite`, `context`, `md5secret`, `qualify`, `disallow`, `allow`, `fullcontact`, `ipaddr`, `port`, `regseconds`, `lastms`, `username`, `defaultuser`)
VALUES (‘ext10′, ‘dynamic’, ‘no’, ‘friend’, ‘yes’, ‘yes’, ‘extensiones’, ‘e8a325cb599ad4b6eb95d79aa4506ed2′, ‘yes’, ‘all’, ‘g729;ilbc;gsm;ulaw;alaw’, ”, ”, ’0′,’0′, ’0′, ”, ”)

Importante, el ultimo valor a 1, y la clave sera 1234 en formato md5 evidentemente se deberia cambiar.

Ahora como antes lo ejecutamos desde el interfaz de comandos de MySQL

#mysql -p
mysql> use asterisk;
mysql> source /etc/usuarios_sip_buddies.sql

Finalmente necesitamos editar el fichero sip.conf con una configuracion minima. Por ejemplo:

/etc/asterisk/sip.conf

[general]
language = es

Desde este mismo momento ya tenemos el usuario sip ext10 con la clave 1234 listo para funcionar. Podemos probarlo con cualquier telefono SIP.

Puede parecer muchisima historia comparado a configurar un fichero sip.conf, pero con la practica y unas plantillas, esta gestion se realiza en 5 minutos y ahora viene la “potencia”.

El script PHP:

Voy a crear un solo fichero PHP al estilo monolitico para que funcione y nada mas. Evidentemente sera bastante mejorable y ya esta en nuestras manos con unos conocimientos basicos de programacion PHP (y obviamente adaptable a cualquier otro lenguaje de programacion con el que nos sintamos mas comodos)

Lo primero vamos a crear algunos directorios dentro del lugar donde tengamos publicado el servidor web apache, por defecto /var/www
# cd /var/www
# mkdir asterisk
# cd asterisk
# mkdir sip
# cd sip

Ahora vamos a crear un fichero index.php con el siguiente contenido:

 <?php

// Conexion a la base de Datos

$base = "asterisk";
$host = "localhost";
$user = "root";
$password = "nuestra_contraseña_sql";
$conexion = mysql_connect($host,$user,$password);
$result = mysql_select_db($base,$conexion) or die ("Error en la Conexion a BD");

session_start();

// Si no estamos logeados

if (!$_SESSION['login'])
{
 if(isset($_POST['loginsubmit']))
 {
 $usuario = $_POST['usuario'];
 $password = $_POST['password'];

 if((!$usuario) || (!$password))
 {
 echo "Error 1<br>";
 exit();
 }
 $password = $usuario.":asterisk:".$password;
 $password = md5($password);
 $query = mysql_query("SELECT * FROM sip_buddies WHERE name='$usuario' AND md5secret = '$password' AND useradmin = '1'");
 if (mysql_num_rows($query) > 0)
 {
 session_register('login');
 $_SESSION['login'] = '1';
 }
 else
 echo "Error 2<br><br>";

 echo "<a href='index.php'>Home</a>";
 }
 else
 {
 echo "<form method='post' action='?'>";
 echo "Usuario: <input name='usuario' type='text'><br>";
 echo "Contrase&ntilde;a: <input name='password' type='password'><br>";
 echo "<input type='submit' name='loginsubmit'>";
 echo "</form>";
 }

}
// Si ya estamos logeados

else
{
 // Salida del Sistema
 if(isset($_REQUEST['exit']))
 {
 session_destroy();

 if(!session_is_registered('login'))
 echo "<a href='index.php'>Home</a>";

 }
 // Insercion de un nuevo Registro
 elseif(isset($_POST['insertsubmit']))
 {
 $sipuser = $_POST['sipuser'];
 $sippass = $_POST['sippass'];
 $sippass = $sipuser.":asterisk:".$sippass;
 $sippass = md5($sippass);
 $query = mysql_query("INSERT INTO sip_buddies (`name`, `host`, `nat`, `type`, `cancallforward`, `canreinvite`, `context`, 
 `md5secret`, `qualify`, `disallow`, `allow`, `fullcontact`, `ipaddr`, `port`, `regseconds`, `lastms`, `username`, `defaultuser`) 
 VALUES ('$sipuser', 'dynamic', 'no', 'friend', 'yes', 'yes', 'extensiones', '$sippass', 'yes', 'all', 'g729;ilbc;gsm;ulaw;alaw', '', '', 
 '0','0', '0', '', '')");

 echo "<a href='index.php'>Home</a><br>";
 echo "<a href='index.php?exit'>Exit</a>";
 }
 // Borrado de un Registro
 elseif(isset($_POST['deletesubmit']))
 {
 $sipid = $_POST['sipid'];
 $query = mysql_query("DELETE FROM sip_buddies WHERE id = '$sipid'");

 echo "<a href='index.php'>Home</a><br>";
 echo "<a href='index.php?exit'>Exit</a>";
 }
 // Formularios de Insercion y Borrado
 else
 {
 echo "Insertar Registro:<br>"; 
 echo "<p><form method='post' action='?'>";
 echo "Usuario: <input name='sipuser' type='text'><br>";
 echo "Contrase&ntilde;a: <input name='sippass' type='password'><br>";
 echo "<input type='submit' name='insertsubmit' value='Insertar'>";
 echo "</form></p>";

 echo "<table border='1'>";
 echo "<tr><td colspan ='2' align='center'>SIP Peers Activos</td></tr>";
 echo "<tr><td>Usuario</td><td>Borrar</td></tr>"; 

 $query = mysql_query("SELECT * FROM sip_buddies WHERE type = 'friend'");
 $rows = mysql_num_rows($query);
 for ($i=0;$i<$rows;$i++)
 {
 $sippeersarray = mysql_fetch_array($query);
 $sipuser = $sippeersarray['name'];
 $sipid = $sippeersarray['id'];

 echo "<tr>";
 echo "<td>".$sipuser."</td>";
 echo "<td>";
 echo "<form method='post' action='?'>";
 echo "<input type=hidden name='sipid' value='$sipid'>";
 echo "<input type=submit name='deletesubmit' value='Borrar'>";
 echo "</form>";
 echo "</td>"; 
 echo "</tr>";

 } 
 echo "</table>"; 
 echo "<a href='index.php?exit'>Exit</a>";

 }
}

?>

Y eso es todo, ahora podemos acceder a traves de un navegador a la direccion:

http://ip_nuestro_servidor_asterisk/asterisk/sip/

Y aparecera para introducir un usuario y contraseña. Siguiendo el ejemplo seria Usuario: ext10,  Contraseña: 1234

Asi accederiamos a la micro interfaz para Crear y Borrar extensiones.

Evidentemente este codigo tiene bastantes deficiencias “tecnicas”, por ejemplo se podria intentar realizar una tecnica de Inyeccion de Codigo SQL para logearnos como el usuario administrador por las “bravas”, y ya conociendo la estructura, hasta darnos de alta un usuario Administrador para acceder siempre. Pero la idea basica era poder ejemplificar lo que queria mostrar con este articulo, que con solo seguir unos pasos de 5 minutos o menos, y tener este script PHP listo para ser “insertado” en el servidor web, tendriamos una interfaz totalmente Autonoma para nuestro cliente, equivalente a la que “instalamos” en mensajes anteriores, para la gestion de salas de conferencias MeetMe.

Ademas esta claro este codigo se podria mejorar para añadir la posibilidad de editar extensiones, o incluso configurar mas parametros de las extensiones (o tener dos interfaces, una de administrador para nosotros mismos, y otra para los usuarios), asi no tendriamos que andar “trasteando” directamente en el interfaz MySQL si modificamos regularmente las extensiones.

Con esto, ya empiezan a haber motivos para poder ir planteandonos dar un primer paso y dar fin a las interfaces graficas de Asterisk!.

Tengo que reconocer que este mensaje me ha llevado componerlo mas tiempo del previsto originalmente. Toda mejora al codigo, o sugerencia como siempre, sera ampliamente agradecida a traves de los comentarios.