KEMBAR78
Blog de Iván López: Google
Mostrando entradas con la etiqueta Google. Mostrar todas las entradas
Mostrando entradas con la etiqueta Google. Mostrar todas las entradas

viernes, 17 de octubre de 2008

Colaborando en un proyecto de Software Libre

   Así dicho, con el título del post parece que estoy colaborando en el desarrollo del kernel de Linux o algo similar. Nada más lejos de la realidad. A un amigo, Jose, le apetecía cacharrear un poco con las APIs de Google, y aprovechando que trabaja con Java, Spring, Hibernate y MySQL se hizo una pequeña aplicación Java para sincronizar sus contactos de Gmail (y toda su información asociada) a una base de datos local MySQL utilizando dicha tecnología. Además, decidió publicar el código en Google Code, en donde Google proporciona un SVN para subir el código, un Wiki e incluso un gestor de incidencias. El resultado lo podéis ver en la web del proyecto GDataUtils (así es como lo llamó). El proyecto está liberado con la GPLv3.

   Como sabe que a mi me gustan estas cosas y tenía ganas de que me enganchara, me contó en un par de horas cómo funciona Hibernate y Spring y cómo configurarlo para que yo pudiera comenzar la parte de la sincronización de Google Calendar (aprovechando que ya conocía un poco el API de Google Calendar).

   Para el que no lo conozca o haya programado en Java picándose a mano las queries contra la base de datos, utilizar Spring + Hibernate es simplemente magnífico. Todo son objetos y por ejemplo insertar en una tabla es crear un objeto que representa a esa tabla, hacer set() de los campos y salvar ese objeto. Automágicamente nuestro objeto se salva en la base de datos. Las búsquedas también son muy simples y si todo lo haces bien en el código java no verás ni una sola sentencia sql. Es realmente cómodo programar así, y aunque en un principio cuesta acostumbrarse y hay bastante fallos debido a la configuración de Spring y Hibernate, una vez que le coges el truco el desarrollo es muy rápido.

   Respecto al código, la parte de sincronización de los contactos (desde Google a la base de datos Local) la terminó Jose hace tiempo y funciona muy bien. Además se guarda un log con todas las modificaciones que se realizan por si es necesario volver atrás. Respecto a mi parte de la sincronización de los calendarios y eventos, está casi terminada aunque todavía sin log. El problema es que tengo este proyecto parado desde hace algún tiempo puesto que ahora estoy centrado en otro que os contaré en breve.

   Por supuesto la aplicación al estar programada en Java es multiplataforma. De hecho Jose programa desde Windows y yo desde Linux y ninguno de los dos hemos tenido problemas con el código del otro.

   Si alguno se anima a probarlo os doy los pasos que debéis seguir para configurar todo. El entorno de desarrollo, como no podía ser de otra forma es Eclipse, aunque recomiendo instalar EasyEclipse puesto que incluye un montón de plugins y configuraciones que nos harán la vida más fácil.
  • Instalar MySql 5: Desde linux es tan sencillo como hacer $ sudo apt-get install mysql-server-5.0 mysql-client-5.0.
  • Instalar ant: En EasyEclipse ya está incluído.
  • Crear en mysql un esquema que se llame gdata (o como queramos) y que esté vacío.
  • Configurar el repositorio SVN del proyecto y hacer el checkout. En la web del proyecto tenéis información sobre cómo configurar el repositorio. Además, podéis navegar por la estructura de directorios y archivos y ver los últimos cambios que se han hecho.
  • Editar el archivo config/hibernate.properties y cambiar los parámetros de la conexión a mysql.
  • Editar el archivo config/SpringConfiguration.xml y añadir el nombre de usuario (con @gmail.com) y password para poder acceder a la cuenta de Google. Esta información sólo se utiliza para conectarse a Google y obtener los contactos. No se almacena en ningún sitio y por supuesto nosotros no tenemos acceso a ella. De todas formas el código está ahí para que veáis lo que se hace con esa información. Ventajas de publicar el código :-P.
  • Ejecutar la tarea ant createSchema que se encarga de crear las tablas necesarias en la base de datos.
  • Ejecutar la tarea ant distrib: Creará el directorio target en el que se encuentra la aplicación ya compilada y lista para su ejecución.
  • En target/distrib ejecutar la tarea ant SyncFromGData.
  • Y listo, mirar la base de datos y examinar la copia de tus contactos.

  •    Dicho así, la verdad es que parece muy complicado (a mi me lo pareció la primera vez), pero luego, una vez que lo haces ves que es sencillo. Además, la mayoría de las tareas sólo es necesario ejecutarlas una vez. Puedes lanzar sucesivamente la sincronización puesto que comprueba si los datos ya se han descargado para no duplicarlos. Además, también actualiza los cambios que hagamos en los contactos.

       Si queréis ejecutar la sincronización de calendarios y eventos el proceso es similar (muchos pasos no hay que repetirlos) y sólo tendréis que cambiar la última tarea ant por la de GoogleCalendar.

       Aunque todo esto así parezca que no es útil y que no tiene mucho sentido, a mi me ha servido para conocer Spring y Hibernate, me ha abierto un mundo nuevo que desconocía y me he actualizado porque como he dicho alguna vez me quedé en Java 1.4.2 y hacía bastante que no programaba en serio.

       Lo realmente interesante de todo es que está realizado completamente con software libre: Google proporciona el SVN para el código, Spring, Hibernate, MySql, Eclipse... Todo es software libre. Además en mi caso, con Linux, hasta el sistema operativo. Lo único que quedaba era Java y hace ya algún tiempo que Sun lo liberó con licencia GPLv2.

       Si alguien se anima a desarrollar la sincronización de GoogleReader, GoogleNotebook,... lo que sea, que me lo diga y vemos cómo empezar.
    ¿Alguna duda?

    viernes, 14 de septiembre de 2007

    Wardriving y geoposicionamiento de puntos de acceso wifi con Google Earth

       Según la Wikipedia, el Wardriving es:
    La búsqueda de redes inalámbricas Wi-Fi desde un vehículo en movimiento. Implica usar un coche o camioneta y un ordenador equipado con Wi-Fi, como un portátil o una PDA, para detectar las redes.
       Además, si en la ecuación utilizamos también un GPS podemos geoposicionar dichos puntos de acceso.

       Yo he modificado ligeramente esta idea utilizando la PDA con el GPS y aprovechando los paseos que damos por las tardes con Judith. Así, sirviendome del mágnifico programa para buscar redes wifi WiFiFoFum y enlazando éste con el GPS he ido almacenando logs con los distintos puntos de acceso wifi que he ido encontrando en sucesivos paseos. Hasta aquí todo muy bien, pero tener un log como este no sirve de mucho:
    0001386FCE3D WLAN_D6  AP On  20:16:57 20:18:03 40,2397633333333 -3,77285833333333
    0002CF503AE3 WLAN_11 AP On 20:24:54 20:26:21 40,24089 -3,77058833333333
    0003C9D1E558 Comtrend AP On 19:58:44 20:04:13 40,244575 -3,77372
    000F213108CF Mota AP On 20:20:43 20:22:17 40,239985 -3,77503166666667
    0011E3E40BD0 THOMSON AP Off 20:35:02 20:35:03 40,241825 -3,77842333333333

       Pensando cómo mostrar esa información de manera que resultase útil visualmente, busqué información sobre cómo convertir mis logs (en formato CSV pero con tabuladores en lugar de comas) en archivos KML que pudiera importar en Google Earth. Existen webs que convierten datos en CSV a KML, pero después de probar el resultado no me convencía demasiado porque el código generado era demasiado complejo y contenía mucha información inútil. Así, después de buscar algo de información sobre KML me dispuse a crear mi propio generador en shell script y AWK. El resultado es el script gps2kml:
    #!/bin/sh
    #
    # gps2kml.sh: Script de creación de ficheros KML para
    # Google Earth a partir de CSV separados por tabuladores
    #
    # Iván López Martín
    # http://lopezivan.blogspot.com
    #
    DATA_FILE=$1
    KML_FILE=$2
    SKELETON=`mktemp -u`
    WEP=$4

    create_AWK_Skeleton() {
    echo { > $SKELETON
    echo if \(\$4 \== \""On"\"\) icon=\""http://farm2.static.flickr.com/1248/1196978492_72600c8064_o.png"\" >> $SKELETON
    echo if \(\$4 == \""Off"\"\) icon=\""http://farm2.static.flickr.com/1260/1196978476_e1a2070680_o.png"\" >> $SKELETON
    echo print \""<Placemark>"\" >> $SKELETON
    echo print \"" <name>\"\$2\"</name>"\" >> $SKELETON
    echo print \"" <description>\"\$1\"</description>"\" >> $SKELETON
    echo print \"" <Point>"\" >> $SKELETON
    echo print \"" <coordinates>\"\$8\",\"\$7\",0</coordinates>"\" >> $SKELETON
    echo print \"" </Point>"\" >> $SKELETON
    echo print \"" <Style>"\" >> $SKELETON
    echo print \"" <IconStyle>"\" >> $SKELETON
    echo print \"" <Icon>"\" >> $SKELETON
    echo print \"" <href>\"icon\"</href>"\" >> $SKELETON
    echo print \"" </Icon>"\" >> $SKELETON
    echo print \"" </IconStyle>"\" >> $SKELETON
    echo print \"" </Style>"\" >> $SKELETON
    echo print \""</Placemark>"\" >> $SKELETON
    echo } >> $SKELETON
    }

    # Comprobación de parámetros
    if [ "$#" != "2" ]; then
    echo "Uso: `basename $0` fich_datos fich_kml"
    exit 1
    fi

    # Creamos el esqueleto de la función para awk
    create_AWK_Skeleton


    # Escribimos la cabecera del fichero kml
    echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $KML_FILE
    echo "<kml creator=\"gps2kml http://lopezivan.blogspot.com/2007/09/wardriving-y-geoposicionamiento-de.html\" xmlns=\"http://earth.google.com/kml/2.1\">" >> $KML_FILE
    echo "<Folder>" >> $KML_FILE
    echo " <name>APs Wifi Parla</name>" >> $KML_FILE
    echo " <open>0</open>" >> $KML_FILE

    # Cambiamos las comas por puntos
    sed "s/,/./g" $DATA_FILE > .tmp$DATA_FILE

    DATA_FILE=.tmp$DATA_FILE

    # Generamos los puntos
    awk -f $SKELETON -F"\t" $DATA_FILE >> $KML_FILE

    # Escribimos el final del fichero
    echo "</Folder>" >> $KML_FILE
    echo "</kml>" >> $KML_FILE

    # Borramos los temporales
    rm $SKELETON 2>/dev/null
    rm $DATA_FILE 2>/dev/null

       La forma de ejecutarlo es muy sencilla y lo único que necesita es el fichero de entrada con los datos y el fichero de salida. Aspectos a tener en cuenta:
  • Como es una versión de andar por casa no se realizan demasiadas comprobaciones.
  • Se utilizan dos iconos distintos en función de si el punto de acceso tiene cifrado o no.
  • Se generan todos los puntos de acceso en una misma carpeta dentro de GoogleEarth.
  • El fichero generado funciona correctamente en las versiones 4.1.7076.4458 y 4.2.0180.1134 de Google Earth bajo Linux. No lo he probado ni en windows ni con otras versiones, aunque no debería de haber problemas.

  •    Después de filtrar los puntos de acceso duplicados de todos los logs de los distintos días, ejecutamos el script con este fichero de entrada:
    ivan@doraemon:~$ ./gps2kml.sh datosGPS.txt paseoJudith.kml

       Abrimos Google Earth cargamos el fichero recien generado (por si no quereis generarlo) y obtendremos una vista de la zona por la que vivo con todos los puntos de acceso que he ido encontrado.

       Así que ya sabéis, si alguna tarde vais por Parla por esa zona y veis a esta preciosa niña, que sepáis que el que va empujando el carrito soy yo ;-).

       P.D: Después de terminar el script y el post he buscado en la web de WiFiFoFum y me he dado cuenta que desde la versión 2.2.5 del 10 de abril de 2007, el programa permite exportar a KML. ¡Eso me pasa por no utilizar versiones actualizadas! (la mía es de octubre de 2006). De todas formas me ha servido para conocer el formato KML y aprovechar los paseos de Judith. Además, el script se puede utilizar para generar el fichero KML desde otros orígenes que no sean el WifiFofum.

    jueves, 6 de septiembre de 2007

    GoogleReader vs Firefox LiveBookmarks

       Llevo mucho tiempo leyendo mis feeds por medio de los marcadores de Firefox. Así, tengo que ir abriéndolos de uno en uno en solapas, recordando los que ya he leído para no volverlos a leer, guardar en del.icio.us lo que más me pueda interesar,... en fin, que es una tarea bastante manual y tediosa.

       Al poco de que Google lanzara Google Reader comencé a usarlo y de hecho tenía algunos feeds configurados, pero por alguna extraña razón que no recuerdo dejé de usarlo. Hace ya un tiempo me lo volvió a recomendar un compañero y decidí darle otra oportunidad. Siguiendo la propia ayuda que proporciona Google Reader me instalé un plugin para firefox que me permitía exportar mis marcadores al formato OPML y poder importarlos de una manera sencilla con Google Reader. En menos de cinco minutos tenía todos mis feeds en Google Reader y lo único que tuve que hacer fue etiquetarlos correctamente y tuve todo listo para funcionar.

       La verdad es que después de llevar utilizándolo muy poco tiempo pienso "¿cómo he podido vivir sin esto?". Lo que más me gusta de Google Reader es:
  • La gestión de los feeds es realmente buena. Se utiliza un sistema de etiquetas similar al de Gmail y los feeds se refrescan automáticamente. Se pueden mostrar todos o sólo los que están sin leer, se pueden marcar feeds como favoritos,...
  • Las estadísticas (trends) aunque no demasiado útiles, sí son al menos curiosas.
  • Se pueden importar automáticamente los feeds de del.icio.us, flickr, blogger,...
  • Puedes compartir tus feeds o los post que consideres más interesantes. Para ello sólo tienes que publicar una url o un feed y listo, cualquiera puede leer lo que compartas.
  • La posibilidad de leer los feeds de manera Offline. Aunque en los tiempos de las conexiones por modem sí resultaría realmente útil porque te podrías descargar los posts (con un máximo de 2000) y desconectarte, en estos tiempos también viene bien por si hay cortes de adsl o lo que sea. Además, este año durante las vacaciones con wifi, sincronizaba mis feeds y por la tarde podía seguir leyendo en casa.
  • Puedes moverte por la interfaz con atajos de teclado, algo realmente útil para no tener que utilizar en todo momento el ratón.
  • Y la más importante por cortesía de Super Coco en los comentarios, la versión móvil para PDAs y móviles, imprescindible.

  •    Realmente todo me ha gustado mucho, lo único que he echado de menos en el tiempo que llevo usándolo era la opción de búsqueda en los feeds y justo hoy me ha sorprendido Google con el cambio. En definitiva, un DIEZ!.

    domingo, 20 de mayo de 2007

    Usando el API de Google Calendar: Alarmas por SMS

       Hace un tiempo descubrí Google Calendar, y aunque no lo utilizo mucho tiene una característica que me llamó la atención desde el principio. Una vez que defines una cita o evento, puedes asociarle un recordatorio para que te avise por email o con un pop-up si tienes la web abierta; hasta aquí ninguna novedad. Lo realmente novedoso es que también permite avisarte por medio de un SMS al móvil y además, en el caso de España es gratis. Sólo hay que asociar a nuestra cuenta de google nuestro número de teléfono móvil y después de una verificación de identidad podemos añadir el aviso por sms como recordatorio de las citas.

       Teniendo esto en mente pensé que sería realmente útil poder enviar alarmas al móvil con el estado de los servidores de casa. Así, si normalmente tenemos alguna tarea programada en crontab que nos avisa por email cuando termina mal, algún monitor de los servicios, espacio en los filesystems,... podríamos añadir una llamada a un programa adicional que introdujese un evento en nuestro calendario de google para que nos llegara el aviso por medio de un sms al móvil y así estar informados en todo momento del estado de nuestras máquinas :-).

       Pues dicho y hecho, me puse a buscar y lo que encontré no pudo ser mejor. Google proporciona un acceso completo a su API, con ejemplos, foros, y además disponible desde varios lenguajes de programación (Java, .Net, PHP y Python). De todos estos, el que más conozco y con el que más he trabajado (aunque ya haga tiempo que no lo toco demasiado) es Java. Además, tiene la ventaja de que al ser multiplataforma podría monitorizar también máquinas windows.

       Me instalé Eclipse y la máquina virtual de Sun 1.5 (ojo que esto es importante, no funciona con la 1.4.2) por medio de un simple apt-get. De la web de google descargué las librerías cliente para java y me puse a probar alguno de los ejemplos. La verdad es que el código es muy sencillo y está muy bien explicado. Hay ejemplos de autenticación, consulta de los eventos del calendario entre determinadas fechas, alta de eventos, borrado, actualización...

       Después de realizar un par de pruebas tenía un esqueleto que funcionaba aunque había que afinar. Examinando con más detalle las clases con Eclipse y con unas pocas pruebas posteriores terminé la versión 0.1 que permite insertar un evento en nuestro calendario y recibir un aviso por sms en 1 minuto. Aspectos a tener en cuenta del código:
  • Para conseguir que llegue el aviso dentro de un minuto lo que hago es poner la hora de comienzo del evento dentro de 6 minutos y la notificación por sms 5 minutos antes. Aunque por código es posible fijar el recordatorio dentro de 1 minuto, luego, cuando se envía la petición se nos muestra un error diciendo que no es válida.
  • Parece que la clase DateTime de Google no se lleva muy bien con la clase Date. Al principio creé un objeto con la hora actual para asignarselo al comienzo del evento, pero una vez asignado, la fecha que ponía era de dos horas antes!. Lo resolví creando un TimeZone para "Europe/Madrid" y utilizándolo en la creación de dicho objeto. Luego hablando con un compañero y comentándole esas 2 horas de diferencia (yo pensé que debería ser sólo una por eso de que estamos en zona GMT+1), me dijo que, con el cambio a horario de verano hemos pasado "automáticamente" a GMT+2. En fin, misterio aclarado. Gracias Jose!.
  • El programa recibe como parámetros el usuario, el password y el texto que queremos enviar. Aunque a priori no hay limitación en la longitud del texto, al móvil sólo nos llegarán los primeros 57 caracteres.
  • Después de construir la petición y enviarla, por la consola aparece un error. Según he investigado parece como si la versión que utilizo de las librerías de google fuera antigua, aunque realmente estoy trabajando con la última. En principio no afecta al funcionamiento, aunque queda un poco "feo".
  • Adicionalmente, es necesario descargar las librerías mail.jar del API JavaMail y activation.jar del Framework de Sun JavaBeansActivation.

  •    Y ya, sin más divagaciones, el código:
    /*
    * Programa para el envío de alarmas por SMS al móvil por medio del API Google Calendar
    *
    * Iván López Martín
    * http://lopezivan.blogspot.com
    *
    */

    import java.net.URL;
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    import java.util.TimeZone;

    import com.google.gdata.client.calendar.CalendarService;
    import com.google.gdata.data.DateTime;
    import com.google.gdata.data.Person;
    import com.google.gdata.data.PlainTextConstruct;
    import com.google.gdata.data.extensions.EventEntry;
    import com.google.gdata.data.extensions.Reminder;
    import com.google.gdata.data.extensions.When;


    public class EnviaSMS {

    public static void main(String[] args) {

    // Comprobamos los argumentos necesarios: usuario, password y texto del mensaje
    if (args.length < 3) {
    System.err.println("Uso: EnviaSMS <usuario> <password> <texto>");
    return;
    }

    String userName = args[0];
    String userPassword = args[1];
    String sms = "";
    // El máximo son 57 caracteres
    for(int i=2; i<args.length; i++) {
    sms = sms + args[i] + " ";
    }
    sms = sms.trim();

    try {
    URL feedUrl = new URL("http://www.google.com/calendar/feeds/" + userName + "/private/full");

    CalendarService myService = new CalendarService("EnviaSMS");

    // Nos autenticamos en google Calendar
    myService.setUserCredentials(userName, userPassword);

    // Creamos el evento
    EventEntry myEntry = new EventEntry();
    myEntry.setTitle(new PlainTextConstruct(sms));

    Person author = new Person(userName, null, userName);
    myEntry.getAuthors().add(author);

    // Definimos la zona horaria
    TimeZone tz = TimeZone.getTimeZone("Europe/Madrid");

    Calendar cal = GregorianCalendar.getInstance();
    cal.add(Calendar.MINUTE, 6);
    DateTime startTime = new DateTime(cal.getTime(), tz); //6m

    cal.add(Calendar.MINUTE, 1);
    DateTime endTime = new DateTime(cal.getTime(), tz); //7m

    // Definimos la hora de comienzo y de fin del evento
    When eventTimes = new When();
    eventTimes.setStartTime(startTime);
    eventTimes.setEndTime(endTime);
    myEntry.addTime(eventTimes);

    // Añadimos el recordatorio sólo como SMS y que avise 5 minutos antes
    Reminder reminder = new Reminder();
    reminder.setMinutes(new Integer(5));
    reminder.setMethod(Reminder.Method.SMS);
    myEntry.getReminder().add(reminder);

    // Enviamos la petición para insertar el evento en el calendario
    EventEntry insertedEntry = (EventEntry)myService.insert(feedUrl, myEntry);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

       Para la ejecución desde la línea de comandos, he creado un pequeño script:
    ivan@doraemon:~$ cat enviaSMS.sh 
    #!/bin/sh
    #################################
    # Iván López Martín #
    # http://lopezivan.blogspot.com #
    #################################
    SMS_HOME=/home/ivan/workspace/GoogleCalendar

    CLASSPATH=$SMS_HOME/lib/activation.jar:$SMS_HOME/lib/gdata-calendar-1.0.jar:$SMS_HOME/lib/gdata-client-1.0.jar:$SMS_HOME/lib/mail.jar:$SMS_HOME/bin

    java -classpath $CLASSPATH EnviaSMS $@

    ivan@doraemon:~$ ./enviaSMS.sh usuario@gmail.com password "Visita el blog de Iván López. http://lopezivan.blogspot.com"

       En nuestro calendario de google aparece el nuevo evento con las opciones que hemos indicado:

       Y un minuto después, en el móvil el sms:


       Como ya he dicho, se trata de la versión 0.1, aunque me parece que no la voy a modificar mucho más porque lo único que necesito es el envío de los sms. No voy a borrar los eventos del calendario, ni actulizarlos, ni consultarlos desde el programa,...

       Cualquiera es libre de modificar el código, usarlo y mejorarlo siempre que por favor respete el comentario del autor y el enlace a este blog. Además, si lo mejoras por favor házmelo saber para poder actulizar este artículo.

       Que lo disfrutéis...