jueves, 20 de febrero de 2014

Sistema de moniteo de red - Gobierno de Córdoba


Otro de los proyectos implementados mientras trabajé en la Gerencia de Telecomunicaciones y Teleprocesos de la Dirección General de la Función Pública del Gobierno de Córdoba, implicaba el monitoreo de los enlaces de WAN que interconectaban las distintas dependencias de Gobierno con el "Supercentro". Como mencioné en un post anterior, la gerencia tenía entre sus responsabilidades el monitoreo de lo vinculado a las redes de datos y a la telefonía. También mencioné que por decisión política de esa gestión de Gobierno, todos los sistemas y servicios informáticos se concentraron en un solo lugar, conocido como "Supercentro".

Cuando el monitoreo no existía, la típica reacción ante un problema era que las distintas áreas le echaran la culpa/fardo/soga a alguna de las otras áreas de Gobierno, deslindando responsabilidades. Esta espada de Damocles iba recorriendo las distintas áreas (telecomunicaciones, infraestructura, base de datos, área de desarrollo, etc.) hasta que el problema se solucionaba "solo", y todo volvía a la "normalidad".

Demás está decir que los problemas surgían a toda hora, por cuanto la infraestructura informática de Gobierno era (¿es?) un verdadero zoológico de proveedores, marcas, modelos, etc. Era notoria la diversidad de servicios de red que podían detectarse si alguien ejecutaba un sniffer convenientemente ubicado en la topología de la red de datos.

El mecanismo más razonable para determinar de manera fehaciente la causa de un problema, era implementar una herramienta de monitoreo, que entre otras cosas permitiera la alerta temprana de problemas en la red y/o los servidores y posiblitara que los responsable pudiera ser proactivos para encontrar una solución.

Implementación de "Big Brother"

Recordemos la época en cuestión era el año 2000, donde aún no existía Nagios u otras herramientas más o menos elaboradas para monitoreo (sobre Linux, por lo menos). Yo tenía experiencia con SNMP, pero evitaba utilizar HP Open View o algún otro programa propietario similar, con el agregado de que me molestaba tener que ir personalmente hasta la pantalla del equipo para determinar el estado de situación de la red.

En base a algunos artículos aparecidos en la Linux Journal hasta ese entonces, teníamos conocimiento del programa "Big Brother", que aún existe. A priori, por el hecho de que fuera de código abierto y accesible mediante un navegador, reunía mis preferencias de mínima para un sistema de esta naturaleza.

El primer paso fue el monitoreo de los enlaces entre Gobierno y sus dependencias. Esto nos permitiría impedir que futuros problemas arrastrara a nuestra área, siempre que esta herramienta así lo demostrara.

Como parte de la desmesura que implicó la concentración abrupta de todos los sistemas en el Supercentro, se estableció un esquema de enlace duplicado con todas las dependencias de Gobierno. Los proveedores de los enlaces, con un buen criterio, debían ser de distintos proveedores. En la práctica, estos proveedores eran Telecom y Techtel. Telecom proveía lineas digitales de 512 kbps, y Techtel, líneas inhalámbricas de 1Mbps (estos valores de ancho de banda fueron mutando en el tiempo, aunque se mantenía la relación 2 a 1). Algunas dependencias del interior de la provincia no tenían cobertura de Techtel, así que el segundo proveedor redundante era Impsat, que utilizaba enlaces satelitales.

Para no complicar el tema de la gestión de los equipos, el encargado de la administración iba a ser un solo proveedor, y la gente de Techtel se propuso como candidato para ello (la gente de Telecom, con astucia, decidió apartarse de lo que a todas luces pintaba como un futuro caos). El mecanismo para "balancear la carga" entre ambos enlaces era mediante la utilización del protocolo "HRSP" entre ambos enlaces, que en principio iba a permitir que el tráfico se distribuyera de manera homogénea.

Demás está decir que había pocas esperanzas para un funcionamiento óptimo del balanceo de carga, en donde ambos enlaces fueran utilizados de la manera más eficiente posible. No solo era complicado imaginar un uso proporcional del ancho de banda en ambos enlaces, sino que este análisis ni siquiera era adecuado, por cuanto los demás valores que definen la calidad de una comunicación (latencia, por ejemplo), diferían notoriamente ya que la tecnología empleada en ambos enlaces era distinta. Lo cierto era que Techtel cobraba un plus por "balanceo de carga", y nunca lo pudieron hacer funcionar correctamente: el enlace de Techtel era el principal, y el enlace de Telecom entraba en acción cuando el enlace principal se caía (o sea, ruteo dinámico liso y llano).

El costo de cada enlace eran elevado. La cantidad de dependencias conectadas por duplicado eran aproximadamente unas 100. Entre las dependencias podemos encontrar: Dirección de Rentas, Catastro, etc., de indudable peso en el funcionamiento del estado provincial. Otras dependencias conectadas eran Teatro Real, Museo Caraffa, etc., que requerían del doble enlace porque poseían 1 (una) PC con algunos sistemas (como el de Rentas por ejemplo), que hubiese permitido que alguien realizara un trámite de Rentas en el mencionado teatro, por ejemplo. Esto último es un despropósito injustificable por donde se lo mire.

Obviando estas consideraciones que exceden lo técnico, realizamos las primeras pruebas con Big Brother, y empezó a dar sus frutos. Hubo que realizar algunas modificaciones para que el programa funcione mejor. Por ejemplo, la cantidad de enlaces monitoreados era tan grande, que el comando ping que utilizaba por debajo para chequear conectividad empezó a hacer agua por el timeout que posee. Esto se solucionó reemplazando ping por fping.

Con los primeros resultados, quedó en evidencia que los enlaces de Techtel poseían intermitencias (la jerga difundida en Gobierno lo identificaba como "micro-corte", aunque no tenían nada de "micro"). Esto fue solucionado luego de algún tiempo (un par de años) cuando ya era indisimulable para el proveedor. En el medio, se puso en duda la precisión de la herramienta, la intencionalidad de los clientes (o sea, nosotros), etc. La solución al problema fue lograda cuando Techtel migró sus enlaces, reemplazando la abusada frecuencia de 2.4 Ghz, por una frecuencia exclusiva arriba de los 5 Ghz.

Este primer uso permitió que nuestra área quedara fuera de las posteriores repartos de responsabilidades ante un nuevo problema, ya que este programa, de fácil acceso para cualquiera, demostraba (o no) que los enlaces de datos no eran la fuente del inconveniente.


Implementación de "MRTG"

Teniendo en cuenta el background que ya tenía en SNMP, parecía lógico que chequearamos la utilización del ancho de banda. Para ello recurrimos a MRTG. De manera similar a Big Brother, este programa es de código abierto y genera información accesible mediante un navegador. En la aspecto técnico la cuestión parecía sencilla, aunque en el formal las cosas son más complicadas.

Lamentablemente hubo reticencia, particularmente de Telecom, para habilitar el servicio de SNMP en algunos equipos, aduciendo razones de "seguridad". Como parte del monitoreo, teníamos interés en determinar la utilización del enlace a Internet, para lo cual se debía habilitar el servicio de SNMP en el router, de esa forma podíamos consultar los contadores de las interfaces WAN. El encargado de seguridad de Telecom procedía a ignorar mis pedidos en ese sentido, ya que si de él dependía, el equipo mejor hubiera estado apagado para lograr una seguridad "casi" perfecta. Poco importaba que, a pesar de su excesivo celo, y a pesar de que el Supercentro tenía control de acceso con guardia policial durante todo el día, igualmente el "naranjita" de calle Ituzaingó ingresaba para utilizar los sanitarios, sin ningún tipo de control adicional más que su sola imagen. A pesar de este tipo de consideraciones "relajadas" en cuestiones de seguridad, Telecom seguía siendo inflexible para con los accesos "virtuales" a sus equipos. Esto nos forzó a habilitar el servicio de SNMP mediante un disimulado proceso de recovery en el router, el cual cumplió su función por varios años, hasta que fue descubierto. Otros proveedores, como Advance (Telefónica), no solo que habilitaron el servicio sin mayores trabas, sino que el esquema de atención al cliente fue inusualmente eficaz, escalando la consulta al nivel 2 de soporte rápidamente, en cuanto determinaron que el requerimiento excedía sus facultades.

Una vez que el servicio de SNMP fue habilitado, procedí a realizar algunas modificaciones en el código de Big Brother, habilitando un enlace en el código html generado, que permitiera relacionar ambos programas. MRTG dejaba en evidencia que el enlace de Telecom estaba principalmente ocioso. Por otra parte, los "traps" de SNMP dejaban también en claro que las caídas de los enlaces de Techtel debido a desconexiones en el medio inalámbrico, eran mucho más frecuentes que lo que pudiera detectar un chequeo de conectividad, que suele tener una cadencia de 5 minutos (los "traps" de SNMP nunca se perdían, ya que encontraban su camino por el enlace de Telecom, cuando el enlace de Techtel se caía, y dejaban en evidencia que los "macro-cortes" eran mucho más frecuentes que lo que pudiera acusar Big Brother).


Interfaz de la información

La pantalla principal de "Big Brother" mostraba un agrupamiento de enlaces en base al proveedor o a la geografía, como se muestra a continuación:

 
Cada agrupamiento permitía ingresar a un listado específico de enlaces. En el caso de "Conexiones Telecom" por ejemplo, el listado se veía de la siguiente manera:


o en el caso de Techtel: 


Para cada enlace listado, se puede acceder a información específica del mismo:



El botón "HISTORY" provee un histórico de las últimas 36 horas:


La barra de imagen que muestra las caídas en las últimas 36 horas no es la original del producto, porque por la cantidad de cortes que tenía un enlace, a veces el gráfico generado era una cebra ininteligible roja y verde. La imagen se regeneró con mayor nivel de detalle gracias a un script externo y el uso de la librería GD.

En la página del enlace en cuestión, se pueden observar las modificaciones realizadas al código generado, que permitían relacionar un enlace con su gemelo del otro proveedor, o con la dirección de LAN del router. La opción "Gráfico Comparativo" mostraba el histórico de los tres puntos de monitoreo asociados a una dependencia:

Desde la opción del listado de los enlaces se puede acceder a la opción del "gráfico de carga" que muestra la pantalla de MRTG asociada:






Ese ejemplo muestra el nivel de uso de los enlaces de algunas dependencias de Gobierno.

Al final de cada listado de proveedor, existían otros agregados:



El "Registro de Reclamos", permitía que el encargado de mesa de ayudas pudiera dejar asentada la información de un reclamo efectuado al proveedor, si se constataba un problema en un enlace. Esa información iba a quedar disponible para que cualquier otra persona vinculada pudiera seguir el estado del reclamo. La pantalla del registro de reclamos se veía como sigue:



y una vez seleccionado el enlace:


entre la información de utilidad para la gente de mesa de ayudas, estaba: teléfono de la dependencia, contacto técnico de informática en el lugar, que permitía constatar el problema (y descartar otras causas, como corte de luz, por ejemplo), y los números de linea y referencia necesarios para generar el reclamo en el proveedor. Esta información estaba almacenada en una base de datos tipo gdbm.

En cuanto a la opción "Enlaces Inestables" del listado para cada proveedor, se accedía a un script que generaba un "ranking" de enlaces más inestables en las últimas 24 horas, en función de la información de Big Brother (este desarrollo fue hecho casi por necesidad, para demostrar la intestabilidad de los enlaces inalámbricos):




Como es habitual, los scripts agregados están desarrollados en perl. Además, las imágenes en este último caso fueron generadas con el apoyo de la librería GD y el módulo perl correspondiente.


Conclusión

Como en el caso del post anterior, se utilizaron aplicaciones de código abierto para facilitar tareas de gestión, de fácil implementación y acceso para su uso compartido entre múltiples personas, y a costo cero. El servidor con HP-UX y HP Open View instalado en supercentro siguió en su ostracismo, tal como sucedía anteriormente, pero ahora plenamente justificado. 

La contundencia con que Big Brother provee la información útil (un simple vistazo general permite determinar si hay problemas, en base al color de la pantalla), permitió que todos los involucrados se familiarizaran rápidamente con su uso. Con el tiempo, y gracias a la existencia de programas cliente de Big Brother existentes tanto para Linux como para Windows, se agregó el monitoreo a los servidores basados en Windows, detectado de esta manera la caída de servicios, los errores en logs, etc.

Al igual que en el caso del tarifador, ese sistema cayó en desuso en cuanto no hubo nadie más que realizara las tareas de configuración, desarrollo y mantenimiento mínimas que requieren productos de esta naturaleza. Probablemente en reemplazo se haya vuelto a recurrir al uso del chamán, para que con sus huesos de pollo intentara determinar la causa de los problemas existentes de ahí en más.

martes, 21 de enero de 2014

Sistema centralizado de tarifación telefónica - Gobierno de Córdoba


En el año 2000 ingresé a trabajar a la Dirección General de la Función Pública del Gobierno de Córdoba, específicamente en la Gerencia de Telecomunicaciones. La gerencia, entre otras responsabilidades, debía monitorear y controlar los enlaces de datos entre las dependencias del gobierno provincial, como así también los gastos telefónicos.

Entre las distintas dependencias de gobierno, existía (¿existe?) un probabilidad bajísima de encontrar dos equipos similares, ya sean de red de datos o de telefonía. La adquisición de nuevo equipamiento, que se suele realizar por licitación pública, depende mucho de la disponibilidad de equipos y de los precios del mercado al momento en que se lanza la licitación (existen además otros factores que exceden -y a veces superan en importancia- lo exclusivamente "técnico").

Las centrales telefónicas no escapan a esta lógica. En ese año, las centrales existentes constituían una verdadera arca de Noé tecnológica, lo cual a todas luces complica cualquier gestión posterior de estos equipamientos, porque obliga a mantener gente especializada para cada marca y/o modelo, o bien se deben pagar múltiples contratos de abono para soporte técnico, en relación directa con la variedad de centrales que se posea. Algunas de las centrales existentes en esa época eran:

  • Philips (Casa de Gobierno, Ministerio de la Solidaridad)
  • Ericsson (Central de Policía)
  • Panasonic (Ministerio de Finanzas, Dirección General de Rentas) 
Esta diversidad también era patente entre los programas instalados para consultar la información de tarifación. En Casa de Gobierno por ejemplo, existía una PC instalada con Windows XP conectada a la central mediante puerto serie RS-232. Debido al gran volumen de llamadas producidas por esa central, el programa de tarifación tardaba varias horas en generar un reporte completo. La patética performance de este sistema exigía la necesidad de lanzar un reporte antes de finalizar el turno de trabajo, para que esté listo cuando arrancara la actividad laboral al día siguiente. Esa falta de inmediatez en la adquisición de los datos afectaba la utilidad de los análisis que se pudieran hacer sobre los mismos.


Diseño del sistema de tarifación centralizado

Previo a la etapa de la implementación, y gracias a una estrategia de esa gestión, la mayor parte de los sistemas de Gobierno se habían concentrado en un solo sitio, conocido como "Supercentro". Esto exigía también que la mayoría de las dependencias de Gobierno deban estar conectadas mediante un enlace de datos redundante con ese sitio central. Esto permitió imaginar una solución que permitiera unificar toda la información del accounting de telefonía en un solo sitio.

El concepto natural aplicable, era un modelo de tres capas como el que se muestra a continuación:



El capturador debía subir la información de accounting a una base de datos ni bien esta se genere. Luego se puede acceder a la información almacenada mediante un desarrollo web con soporte CGI, de tal manera que la información solicitada se genere de manera dinámica. La implementación mediante web facilita el acceso a esta información,  ya que no exige la instalación de ningún programa cliente de base de datos específico en la PC del interesado. Además esto restringe el acceso directo a la base exclusivamente para el servidor web y los capturadores.

El sistema web cuenta con un esquema de acceso restringido, de tal manera que se debe
verificar la autenticación de los usuarios que acceden a la información. Además, teniendo en cuenta que existía un organigrama que establece una jerarquía arbolada entre las distintas áreas de Gobierno, esto define que tipo de información puede consultar cada usuario (solo puede ver información relacionada a su propia área o áreas dependientes).

La plataforma natural elegida para todos los elementos integrantes fue Linux, a pesar que en ese momento era inexplicable e injustificadamente resistido por los responsables de la dirección general. Cuando el esquema ya estaba funcionando y con algunos usuarios, la idea de rediseñar todo desde cero con una nueva plataforma se caía por su propio peso, así que no quedó otra alternativa que aceptar el desarrollo tal como estaba.

Capturador de datos de la central

La primer prueba de captura fue  realizada en la central de Casa de Gobierno. Agregamos un equipo que capturara la información de accounting, en paralelo a la PC existente, por lo cual hubo un tiempo de transición en que convivieron ambos sistemas de consulta. Construimos un cable que permitiera la recepción de la salida del puerto RS-232 por más de un receptor. Nuestro equipo de captura no iba a generar datos salientes, así que básicamente se comportaba como un "sniffer" del puerto RS-232 saliente de la central.

El equipo que realizaba la captura era una PC vieja, donada por la empresa de telecomunicaciones "CTI" (actualmente "Claro"). En ese momento, la empresa estaba migrando la tecnología de sus celdas, y estaba descartando PCs. La utilidad de estas PCs como estación de trabajo era limitada. Los modelos de PC eran dos: COMPAQ DESKPRO X466 y XE 450.

Sobre estas PCs marca COMPAQ se generó una imagen con sistema operativo Linux, distribución Slackware. Al funcionar esta PC exclusivamente como un capturador, se prescindía del uso de un monitor y teclado, aunque si era necesario que tuviera conectividad con la red de datos. Se podía acceder remotamente mediante SSH. La única tarea de utilidad del equipo era correr un programa que capturara la información de accounting emitida por la central, parseara los datos útiles de cada llamada, y los subiera por la red a un servidor de base de datos.

El capturador del puerto serie estaba basado en el programa "miniterm", mencionado en el "Linux Programmer's Guide". La operación de extracción de la información de accounting era distinta para cada modelo de central, ya que cada marca y modelo genera la información de accounting como mejor le parece. Por supuesto, no hay estándares en ese sentido, sumado al hecho de que fue bastante dificultoso acceder a la documentación de las mismas. Pareciera que el éxito de este tipo de esquemas se basa en retacear información a los clientes en la medida de lo posible.

Como ejemplo de la información de tarifación de la central philips de Casa de Gobierno, tenemos lineas como las siguientes:

...
* #0171101071720249375                            0474775                         13140000100431000050
* #0172208108881011         0000            000000001000048

* #0173101071720250474764     3514334394          9533                            31030000100931000011
* #0174101071720250474761     3514713779          9354                            31030000100634000038
* #0175101071720259354                            9391                            11140000000334000000
* #0176101071720259321                            0010007                         13140000000331000000
#017724394                0000            000000000000003
* #0178101071720259321                            0010009                         13140000000431000000
* #017924394                0000            000000000000004

...

La ubicación de la información es fija en cada linea, y debe cumplir con un formato prefijado. Por ejemplo, todas las lineas deben comenzar con '*' seguido de un espacio y '#'. A continuación  sigue "'01", y luego hay un número de secuencia que va desde "00" a "99". El siguiente caracter indica si el registro es información estandar (valor '1') o de accounting (valor '2').

Si es un registro estándar, debe tener un largo de 104 caracteres. Este tipo de registros provee información de la fecha: dos dígitos para año, mes, día, hora y minuto respectivamente. Además indica si la llamada es saliente hacia la PSTN (valor '3' en la posición 83), y si fue contestada (valor '1' en la posición 90). También incluye información del número originador de la llamada.

Si es un registro de accounting, debe tener un largo de 61 caracteres. Este tipo de registros informa la duración de la llamada en la posición 53, el número llamado en la posición 8, y la cantidad de pulsos de la llamada en la posición 47. Completa la información del registro estándar inmediatamente anterior (según la numeración de secuencia)


Ejemplo:



En esta primera versión, una vez que se extractaba la información útil de la llamada, se la subía a una base de datos en una operación concurrente, mediante un comando aparte.

Además de la transacción por red, se dejaba una copia del accounting en texto plano en el mismo capturador, por si hacía falta algún análisis posterior sobre la información en crudo. Aquellas lineas que no cumplieran con el formato, eran almacenadas por duplicado en un archivo separado para su posterior análisis.

Subida de los datos de accounting a la base de datos

En esta primera versión, los datos del accounting eran subidos de manera directa a una base de datos Mysql desde el capturador. El programa, también desarrollado en lenguaje "c", utilizaba la API correspondiente de Mysql para conectarse a la base remota.

En cuanto al diseño de la estructura de la base, hubo algunos errores producto de mi inexperiencia en el diseño de base de datos. El volumen de información almacenado era monstruoso, según la central. Teniendo en cuenta que no iban a existir consultas cruzadas entre distintas centrales, procedí a generar una tabla por separado para cada central, con el ánimo de agilizar cualquier consulta, o de restringir los problemas de performance solo a las centrales más grandes.

También generé un esquema de 4 tablas que definían la jerarquía del organigrama de las dependencias de Gobierno. En ese momento no existían más de 4 niveles, aunque nunca nadie tuvo claro cual era la conformación actual del organigrama, ya que las dependencias se creaban o desaparecían con una facilidad pasmosa; ya se sabe, a veces se quiere dar la impresión de que las cosas cambian si se generan algunas nuevas áreas o direcciones, se eliminan algunas otras, o se cambia la relación de dependencia entre ellas.

Web server + CGI

Los programas cgi fueron desarrollados en perl. En esta primera versión, el código HTML estaba embebido en el código perl.

La pantalla principal solicita usuario y contraseña:


La información de tarifación era solo uno de los desarrollos existentes en ese momento. Ingresando correctamente el usuario y la contraseña, se accedía a las opciones de reporte existentes:



La primera opción, mostraba las últimos 20 registros de la central seleccionada. Su principal utilidad era mostrar la dinámica de la información generada, e indicaba una dimensión del volumen de uso que tenía la central:



Gracias a una lista obtenida de la página de la CNC, se pudo determinar la localidad en base a la primera parte del número destino. Como regla general, el rango de números asignados varía entre 100 y 10.000 números, según la localidad que lo solicita. Algunos otros números especiales fueron cargados a mano.


Las siguientes 3 opciones proveen un listado completo del día, ordenado por distintos criterios:
  1. por hora, desde el más reciente al más antiguo:
  2.  por duración de la llamada:
  3.  por número de destino más llamado:
Se podía generar una distribución de llamadas en el último día, con la ayuda de la herramienta GNUPlot para los gráficos:

También se puede generar un reporte para un interno o un identificador específico:
se selecciona un rango de fechas, y muestra la lista correpondiente:

Por último, se pueden generar listados históricos por fecha y por central

el listado se ve como sigue:

El listado podía almacenarse en pdf, mediante el uso del comando "htmldoc":





Conclusión


Puede apreciarse la utilidad de las aplicaciones de código abierto para hacer desarrollos que integren distintas tecnologías. Sumado al software abierto y gratuito, se utilizó hardware de descarte. De hecho, el servidor inicial que integraba tanto la base de datos como el servidor web, también era una PC que estaba abandonada, aunque poseía más recursos que los equipos utilizados para captura (tampoco tanto más).

Con el tiempo, el uso de este sistema empezó a acrecentarse, y eso obligó a las autoridades a mejorar los recursos destinados para la etapa del servidor. Por cierto que la implementación de un sistema de estas características sin costo agregado en hardware o software, no es habitual en este tipo de organizaciones, ni siquiera atendiendo la coyuntura de ese momento (finales de 2001). En esa primera versión, las centrales consultadas eran tres: Casa de Gobierno, Instituto Pizzurno (Ministerio de la Solidaridad - Ministerio de Salud) y Dirección General de Rentas.

En sucesivas entradas, se irá describiendo la evolución que tuvo este desarrollo.

miércoles, 8 de enero de 2014

Live streaming en Ustream con Raspberry Pi + Camera board

La Raspberry Camera board es una placa adicional para Raspberry Pi, que de manera bastante sencilla nos permite agregar soporte de video a la mencionada placa. Solamente debemos conectar el nuevo dispositivo, actualizar el "firmware" de nuestro raspbian, y con eso tenemos la mayor parte del camino allanado. Pero vamos por parte.

Instalación y configuración de la camera board.

Los primeros pasos están bien descriptos en http://www.raspberrypi.org/camera, y básicamente son los siguientes:

  1. Conectar la placa con la RPi apagada, según las instrucciones del video http://www.youtube.com/watch?v=GImeVqHQzsE. Hay que prestar especial atención al sentido del cable.
  2. La cámara queda conectada de la siguiente manera:


  3. Actualizar los paquetes de Raspbian:
  4. sudo apt-get update
    sudo apt-get upgrade
  5. Ejecutar el programa de configuración de RPi:
  6. sudo raspi-config

    y seleccionar "camera" -> "enable"

    Salimos con "Finish". Reiniciamos la RPi.

Primeras pruebas con la cámara

La actualización del firmware nos provee de una serie de comandos adicionales para interactuar con la cámara. Uno de ellos es raspivid, que nos permite capturar video, mientras que raspistill nos permite capturar imágenes.

Algunos ejemplos de uso:

raspistill -o image.jpg (captura una imagen en el archivo image.jpeg)

raspivid -o video.h264 (captura un video de 5 segundos -duración por defecto- en el archivo video.h264).

raspivid nos permite enviar video a la salida por defecto (stdout), y esta funcionalidad es la que aprovecharemos para publicar el streaming.

Podrán encontrar muchos más ejemplos en la referencia mencionada antes. Entre ellos, existen algunos ejemplo sobre mecanismos de streaming utilizando netcat. En las referencias también encontrarán mecanismos para realizar streaming mediante la utilización de cvlc o ffmpeg como fuente de video, y vlc como cliente de streaming.

Utilizando Ustream como destino de nuestra transmisión

Ustream es un servicio muy utilizado para realizar transmisiones por Internet. No es el único en su tipo. Con una registración gratuita, podemos realizar nuestras primeras pruebas.

Una vez que ingresamos con nuestro usuario, podemos crear un "canal". Este canal posee algunas propiedades, entre ellas hay una que se llama "remote". Esta propiedad define el URL al que debemos apuntar con nuestra fuente de video, además de una "llave" que sirve para que nadie más usurpe nuestra transmisión.

La URL completa del destino de nuestra transmisión, está formada por ambos datos.


<url_de_tipo_rtmp>/<key>

Ejemplo:

rtmp://1.22114414.fme.ustream.tv/ustreamVideo/22114414/FKedARaaBeakurSacaADTufB5vaan7SL

Para enviar la salida del comando raspivid hacia Ustream, utilizaremos el comando avconv. La forma sería la siguiente:

raspivid -o - -w 460 -h 270 -t 9999999 |  avconv -r 10 -b 350k -i - -f flv
rtmp://1.22114414.fme.ustream.tv/ustreamVideo/22114414/FKedARaaBeakurSacaADTufB5vaan7SL

En este caso, enviamos un video de dimensiones 460x270 hacia el comando avconv. Este a su vez lo convierte en flv, y lo reenvía a Ustream.

Luego podremos acceder con un navegador a la dirección que Ustream asoció a nuestro canal:

http://www.ustream.tv/channel/nuestrocanaldeprueba

Algunas capturas de la transmisión:



Eso es todo.



Referencias:


http://www.raspberrypi.org/camera
http://www.mybigideas.co.uk/RPi/RPiCamera/
http://sonnati.wordpress.com/2011/08/30/ffmpeg-%E2%80%93-the-swiss-army-knife-of-internet-streaming-%E2%80%93-part-iv/
http://techzany.com/2013/09/live-streaming-video-using-avconv-and-a-raspberry-pi/

miércoles, 1 de enero de 2014

Acceder a Google Drive como una partición de red desde nuestro Debian Wheezy

Suele ser útil el disponer de espacio de almacenamiento on-line que nos permita acceder a ciertos archivos desde distintos hosts. De entre las múltiples opciones existentes, Google Drive es una buena opción, sobre todo si ya contamos con una cuenta de gmail.

En este caso, se instalará y configurará la aplicación google-drive-ocamlfuse para poder utilizar nuestra cuenta de Google Drive como almacenamiento. google-drive-ocamlfuse está basado en fuse, y permite montar y desmontar nuestro almacenamiento en Google Drive como habitualmente lo hacemos con otros sistemas de archivo de red.

Este desarrollo se encuentra alojado en github, por lo que es accesible por cualquiera que pretenda compilarlo desde sus fuentes. De cualquier manera, existen versiones pre-compiladas para Ubuntu que pueden ser utilizadas en Debian Wheezy.

Para ello, debemos disponer del comando add-apt-repository, que forma parte del paquete "python-software-properties". Si aún no lo tenemos instalado, debemos hacerlo:

sudo apt-get install python-software-properties

Ya estamos en condiciones de agregar el repositorio de Ubuntu que contiene los paquetes precompilados instalables de google-drive-ocamlfuse para Ubuntu:

sudo add-apt-repository ppa:alessandro-strada/ppa

Este comando genera el archivo "/etc/apt/sources.list.d/alessandro-strada-ppa-wheezy.list". Si inspeccionamos el contenido del archivo, veremos que la versión que utiliza para definir la entrada del repositorio ("wheezy" en nuestro caso), lo obtiene automáticamente del equipo donde se ejecutó el comando  "add-apt-repository". Lo cierto es que el paquete no está disponible para esa versión de Debian, y si lo está para distinta versiones de Ubuntu. Una versión de Ubuntu aproximadamente equivalente a wheezy, es "precise". Esta equivalencia está dada principalmente, por la versión de libc que utiliza una y otra versión.

Debemos editar el archivo "/etc/apt/sources.list.d/alessandro-strada-ppa-wheezy.list", y reemplazar las apariciones de "wheezy" por "precise". Luego actualizamos la información del repositorio.

sudo apt-get update

Ya tenemos disponible el programa google-drive-ocamlfuse si queremos instalarlo mediante el gestor de paquetes:

sudo apt-get install google-drive-ocamlfuse

Si se instaló correctamente, ya estamos en condiciones de utilizarlo.

Configuración

Al correr el programa google-drive-ocamlfuse por primera vez sin argumentos, se establece el mecanismo de autenticación que permitirá futuras ejecuciones sin mayores complicaciones:

google-drive-ocamlfuse

Esta primera ejecución, entre otras cosas, abre un navegador que nos solicita el ingreso en nuestra cuenta de gmail, para poder autorizar el acceso a esta aplicación. Si la autorización finaliza de manera exitosa, ya podemos utilizar el comando para montar y desmontar nuestro almacenamiento en Google Drive.

Podemos crear un directorio vacío que utilizaremos como punto de montaje para el almacenamiento:

mkdir ~/GDrive

Luego montamos nuestro almacenamiento remoto, de la siguiente manera:

google-drive-ocamlfuse ~/GDrive/

Una vez montado, podemos acceder con los comandos habituales para interactuar con un directorio. Ejemplo:


ls -l ~/GDrive/


Una vez finalizada la interacción con el almacenamiento remoto, podemos desmontarlo de la siguiente manera:

fusermount -u ~/GDrive/

Eso es todo.


Referencias:
http://gdfuse.forge.ocamlcore.org/

viernes, 30 de agosto de 2013

Migración de Proyectos de Anjuta 1.x a 2.x

(english version)

Anjuta es una herramienta que durante años me ha sido de gran utilidad. Si bien la herramienta fundamental para el diseño de interfaces que utilizan Gtk+ es Glade, el hecho de que Anjuta provea cierto nivel de integración entre los distintos elementos necesarios para el desarrollo (glade, el editor scintilla) facilita aún más las cosas.

Dicho esto, tenemos claro entonces que nada impide desarrollar los distintos componentes de nuestro programa por separado: podemos mantener una sesión de glade para ir modificando las ventanas de nuestra interfaz; paralelamente utilizamos algún editor de texto para ir modificando nuestro código. Con una terminal adicional podemos ejecutar y depurar las compilaciones parciales de nuestro programa. Anjuta provee todas estas operaciones de manera integrada.

Para facilitar aún más esa integración, Anjuta 1.x proveía un conjunto funciones que facilitaban algunas tareas (lookup_widget(), p. e.). En versiones más recientes de Anjuta ese soporte dejó de existir, porque se prioriza la utilización directa de la librería libglade. Esta librería permite enlazar el programa y la pantalla desarrollada con glade en tiempo de ejecución. En Anjuta 1.x, la relación entre la interfaz y el código se establece durante la compilación, mediante un conjunto de funciones adicionales provistas por el mismo Anjuta (definidas en el archivo support.c).



Familiarizándonos con la interfaz de Anjuta 2.x

Una vez que instalamos la nueva versión de Anjuta, saltan a la vista algunas diferencias con la versión anterior. La más significativa quizás sea que la combinación de teclas "Alt+G" no arranca Glade como antes. A no desesperarse, la forma de interactuar con Glade ahora es mucho más natural: simplemente hay que dar doble click al archivo que define la interfaz de nuestro programa.


Otra diferencia notoria, es que Anjuta dispone ahora de varios perfiles de compilación predefinidos. Esto no es otra cosa que la combinación de flags del compilador necesarias para generar un proyecto optimizado para su ejecución (-O3), optimizado para debug (-g), etc. Al momento de construir nuestro proyecto, elegimos el tipo de perfil que deseamos.

Abriendo un proyecto "viejo" con Anjuta 2.x


De entre todas las opciones que disponemos para abrir un proyecto viejo, personalmente prefiero la opción "Archivo -> Nuevo -> 5. Proyecto desde fuentes existentes".



Una vez seleccionada esa opción, buscamos el directorio que contiene el proyecto "viejo":

El nombre sugerido para el nuevo proyecto, es el mismo que el directorio seleccionado. Podemos modificarlo si así lo deseamos. A continuación, nos consulta por el tipo de backend que queremos para el proyecto que estamos importando. En mi caso, elijo "Backend de autotools".



Finalmente Anjuta genera el nuevo proyecto: 



puede notarse que a la izquierda figuran todos los archivos heredados del proyecto viejo.

Si intentamos la combinación de teclas "Mayus+F7", nos pregunta por el tipo de perfil de compilación que queremos utilizar:



Elegido el tipo de perfil, intenta construir el binario. No lo logra. Intentaremos superar esta situación.



Acomodando el proyecto recién importado

Como comenté anteriormente, muchas funciones de soporte que proveía Anjuta 1.x, ya no son necesarias. Básicamente se puede prescindir de los archivos: "suport.c", "suport.h", "interface.c" e "interface.h". Se pueden eliminar de varias formas. En mi caso, el directorio importado forma parte de un directorio de trabajo de un proyecto almacenado mediante "subversion", así que utilizo la siguiente opción:



de esta forma, eliminamos todos los archivos mencionados. Además, se deben eliminar las referencias a estos archivos que ya no estarán; en particular hay que editar el archivo "src/Makefile.am", para eliminar las apariciones de los archivos arriba mencionados. Luego debemos posicionarnos desde una consola en el directorio, y ejecutamos el comando "./autogen.sh".

Este último comando no solo regenera el archivo "Makefile", para que no tenga más en cuenta los archivos eliminados. Es probable que muchos utilitarios empleados por nuestro proyecto viejo hayan cambiado desde la última vez que lo modificamos, no solo Anjuta y Glade ("automake", "autotools", etc). "./autogen.sh" se encarga de acomodar las versiones de estos programas en el proyecto importado.

Con un poco de suerte, el intento de generación del binario empezará a fallar por el contenido de los archivos fuente, y no por el armado del proyecto en sí. Para empezar, los programas fuente todavía harán referencia a los archivos de cabecera eliminados ("suport.h" e "interface.h"). Podemos eliminar esas líneas en nuestro código.

Por supuesto, no alcanza solo con eliminar estas líneas. Todavía quedan muchas referencias a las funciones incluídas en esos archivos eliminados que deberemos reemplazar. El siguiente punto enumera algunas de ellas.



Modificando el código fuente para una compilación exitosa

El primer intento de compilar nuestro código nos muestra una pantalla como la que sigue:




vemos una seguidilla de mensajes de alarma, que nos avisa sobre ciertas funciones que dejaron de estar definidas para el código, a saber: "add_pixmap_directory", "lookup_widget", "create_window", etc. Deberemos reemplazarlas.

En mi caso, he abusado bastante de la función "lookup_widget" en mis proyectos. Básicamente esta función obtenía el widget a partir del nombre del mismo , y para ello barría todo el árbol de dependencias del widget del programa hasta que lo encontraba, en un mecanismo poco eficiente. En cambio, ahora utilizaré la librería "libglade", que analiza el contenido del archivo ".glade" en tiempo de ejecución y realiza las ligaduras necesarias entre los nombres de los widgets, las funciones de callback asociadas, etc. La forma de utilizar libglade, es mediante el uso de GtkBuilder, que parsea el archivo "xml" en tiempo de ejecución, crea los widgets, configura sus propiedades, y asocia las funciones de callback que están definidas en nuestro código. Además, se crea una estructura con punteros a todos aquellos widgets que deban ser accedidos en las funciones de callback (que no sean aquellos widgets cuya acción está asociada a la función), los cuales se inicializan al momento de crear el builder, y de esa manera pueden ser accedidos en cualquier momento.

La primer corrección que realizaré, es la reformulación de la función genéricamente conocida como "create_window()" ("create_ventana_principal()", en mi ejemplo), que desapareció al eliminarse el archivo "interface.c":

La linea:

ventana_principal = create_window ();

Se convierte en:

item = g_slice_new(ItemStruct);

if (create_window(item) == FALSE) {
      logmsg("Error al crear pantalla");
      return(-1);
}


El argumento de la función "create_window()", es un puntero a la estructura que agrupa los widgets que deban ser accedidos en las funciones de callback. A priori no conozco el contenido de la estructura, sino que la iré armando a medida que avance en el proceso de recompilación exitosa del programa. Por lo pronto, incluye al menos un elemento: el puntero al widget "ventana_principal". Un buen lugar para definir esta estructura es el archivo "callbacks.h":

typedef struct {
   GtkWidget       *ventana_principal;
} ItemStruct;

ItemStruct *item;

Podemos definir la función "create_window()" en el mismo archivo "main.c":

gboolean create_window (ItemStruct *item)
{
   GtkBuilder *builder;
   GError* error = NULL;

   builder = gtk_builder_new ();
   if (!gtk_builder_add_from_file (builder, UI_FILE, &error)) {
      g_warning ("No puedo crear builder a partir del archivo: %s", error->message);
      g_error_free (error);
      return FALSE;
   }

   /* Asocia el widget cuyo nombre es "ventana_principal", con el elemento de la estructura que lo va a representar */
   item->ventana_principal = GTK_WIDGET (gtk_builder_get_object (builder, "ventana_principal"));

   /* Asocia las señales */
   gtk_builder_connect_signals (builder, item);

   g_object_unref (builder);

   return TRUE;
}

Esta función también es el lugar propicio para definir cualquier cuestión relacionada a la definición estética de nuestra interfaz, que no esté ya contemplada por el archivo ".xml" de glade, o en el archivo "rc" que estemos usando. UI_FILE es un macro que define el path al archivo ".xml" de glade.

Al comentar o eliminar aquellas lineas donde utilicé la función "
lookup_widget()", se generan los siguientes mensajes en los sucesivos intentos de compilación:

main.c:XXX: error: 'my_variable' undeclared (first use in this function)

La variable "my_variable", que es un puntero a un widget cuyo valor se completaba con el uso de la función "lookup_widget()", ahora debe ser parte de la estructura mencionada anteriormente, y debe inicializarse durante la invocación de la función "create_window()". La estructura quedaría conformada de esta manera:


typedef struct {
   GtkWidget       *ventana_principal;
   GtkWidget       *my_variable;
} ItemStruct;

ItemStruct *item;



Y en la función "create_window()" agregamos la asociación a este nuevo puntero de widget:

      ...

   /* Asocia el widget cuyo nombre es "ventana_principal", con el elemento de la estructura que lo va a representar */
   item->ventana_principal = GTK_WIDGET (gtk_builder_get_object (builder, "ventana_principal"));



   item->my_variable = GTK_WIDGET (gtk_builder_get_object (builder, "my_variable"));


      ...



En la linea donde el compilador acusó el mensaje de error, se debe reemplazar la aparición de "my_variable" por el elemento de la estructura. Ejemplo:

gtk_widget_modify_font(GTK_WIDGET(my_variable), pfd);

se debe reemplazar por:

gtk_widget_modify_font(GTK_WIDGET(item->my_variable), pfd);

De a poco vamos agregando todos los widgets que deben ser accedidos, y que por ende deberán ser incluidos en la estructura, de tal manera que no se obtengan más esos mensajes del compilador. Este tipo de reemplazos deberemos realizarlos tanto en "main.c" como en "callbacks.c".

En relación a la función "add_pixmap_directory()", en principio podemos evitar su uso, por cuanto la relación a los archivos de imagen está definida en el archivo ".glade". De cualquier manera, si necesitamos referirnos a alguna imagen en particular, podemos utilizar la función "glade_xml_get_widget()".


Con un poco de suerte, nuestro compilador dejará de informarnos que existen errores o faltantes en nuestro código. Igualmente, si queremos ejecutar el código, probablemente aparezcan errores o bien se vea horrible. Esto es porque debemos corregir el archivo ".glade" aún.





Adaptando el archivo de interfaz a la nueva versión de Glade

Existen algunas diferencias entre las versiones de glade 2 y 3, en relación a las marcas de xml que definen los distintos widgets. Aquí van algunas de ellas:


  • La marca <glade-interface> ahora es <interface>, y la marca de cierre pasa de ser </glade-interface> a </interface>
  • La marca <widget class= ahora es <object class=, y la marca de cierre pasa de ser </widget> a </object>
  • Además a los widgets tipo "GtkVBox" y "GtkVPane" hay que agregarles la propiedad <property name="orientation">vertical</property> para que los widgets no se vean apaisados.
  • Los widgets de tipo "GtkComboBox" que muestra una lista sencilla de texto presentan cambios en versiones más nuevas de GTK+. Si bien existe un widget "GtkComboBoxText" que se asemeja bastante al anterior, este no es reconocido por glade 3.12.1, por lo cual si queremos seguir utilizando glade, debemos utilizar el modelo de lista e integrarlo al GtkComboBox. Los pasos se detallan a continuación:
  1. Desde anjuta, se debe asociar el widget "GtkComboBox" a un modelo de ComboBox. Este modelo se define por separado, y en él se establecen cuántas columnas va a tener, y que tipo de datos va a incluir cada una. Cada columna se identifica con un nombre distintivo. Además se pueden precargar valores en el listado. En el caso de las listas sencillas de texto, la cantidad de columnas va a ser 1, de tipo "gchararray". Una vez definido el modelo de lista, con el botón derecho del mouse sobre el widget se debe acceder a la opción "Editar...", -> pestaña "jerarquía" -> "añadir" una nueva jerarquía donde se define el nombre, el tipo, y a que atributo estará relacionado (en principio, el atributo elegido es el correspondiente a la única columna definida previamente en el modelo). 
  2. En lo correspondiente al código del programa, se deben realizar los siguientes reemplazos:
          // Bucle para completar el ComboBox
          while ( ... ) {
              gtk_combo_box_append_text(GTK_COMBO_BOX(comboBox), item);
          }

por


          GtkListStore *listaModelo;
          GtkTreeIter iter;


          // Bucle para completar el ComboBox
          while ( ... ) {
              gtk_list_store_append (listaModelo, &iter);
              gtk_list_store_set (listaModelo, &iter, 0, item, -1);
          }
          // se asocia la lista al ComboBox 
          gtk_combo_box_set_model(comboBox, GTK_TREE_MODEL(listaModelo));
          // "elementoLista" es el widget creado cuando se definió la jerarquía
          gtk_cell_layout_add_attribute (comboBox, elementoLista, "text", 0);

Aún puede aparecer un mensaje de error en tiempo de ejecución, del tipo "Could not find signal handler  ... ". Este mensaje indica que no se encuentra la definición de señales definidas y asociadas a algún widget (típicamente definidas en el archivo "callbacks.c"). Para evitar que se presente este error, se debe compilar el proyecto con el flag adicional "-export-dynamic". Esto se puede definir desde el menú "Construir -> Configurar el proyecto ... -> Opciones de configuración:", agregando 'CFLAGS=-export-dynamic'

Referencias:
http://www.micahcarrick.com/gnome-anjuta-programming-tutorial.html
http://www.micahcarrick.com/libglade-anjuta-tutorial.html
http://www.micahcarrick.com/gtk-glade-tutorial-part-1.html
http://www.micahcarrick.com/gtk-glade-tutorial-part-2.html

http://www.micahcarrick.com/gtk-glade-tutorial-part-3.html
http://www.micahcarrick.com/gtk-glade-tutorial-part-3.html
http://www.micahcarrick.com/gtk-glade-tutorial-part-4.html
http://old.nabble.com/please-help:-bug:-glade2-file-conversion-to-glade3-failed-td26467085.html
http://ubuntuforums.org/showthread.php?t=1377005

"Creating GtkComboBox using Glade":
http://www.youtube.com/watch?v=Z5_F-rW2cL8

"gtk_combo_box_append_text() problem":
http://permalink.gmane.org/gmane.comp.gnome.glade.user/3774