Dec 25

Introducción

OpenNI (Open Natural Interaction) es una organización sin ánimo de lucro enfocada en el desarrollo de tecnologías para la interacción natural con dispositivos.  Uno de sus principales participantes es PrimeSense, una empresa israelí responsable del desarrollo del Kinect y dispositivos similares junto con la firma Asus.

Su framework provee una infraestructura genérica basada en APIs de código abierto para acceder a los dispositivos de interacción natural, sobre él se instala el Sensor que permite acceder específicamente a los servicios provistos por el Kinect.  Adicionalmente esta empresa desarrolla el middleware NITE el cual no es de código abierto y permite acceder a funcionalidades avanzadas como seguimiento del esqueleto en tiempo real y  reconocimiento de gestos entre otras cosas.

Este proedimiento fue verificado en equipos utilizando GNU/Linux Ubuntu 11.10 y Mint 12.

Aviso!  Se instalarán las versiones inestables de OpenNI y NITE ya que actualmente así lo sugiere el módulo de SensorKinect modificado por avin2.

Prerequisitos

$ sudo aptitude install build-essential python libusb-1.0-0-dev freeglut3-dev openjdk-7-jdk doxygen graphviz

Si se desea instalar el soporte para .NET es necesario contar previamente con el soporte para Mono instalado.

$ sudo aptitude install mono-complete

Instalar OpenNI

$ mkdir ~/kinect ; cd ~/kinect

$ git clone https://github.com/OpenNI/OpenNI.git -b unstable

Aviso!  Si hay problemas con la siguiente ruta verificar si existe el directorio Linux o Linux-x86 ya que he visto algunas variaciones entre las pruebas que realicé a finales de diciembre del año pasado y esta versión mas reciente.

$ cd OpenNI/Platform/Linux/CreateRedist

$ bash RedistMaker

$ cd ../Redist/OpenNI-Bin-Dev-Linux-x86*/

$ sudo ./install.sh

Instalar Sensor Kinect

$ cd ~/kinect

$ git clone https://github.com/avin2/SensorKinect

$ cd SensorKinect/Platform/Linux/CreateRedist

$ bash RedistMaker

$ cd ../Redist/Sensor-Bin-Linux-x86*

$ sudo sh install.sh

Instalar NITE

Descargar la distribución binaria para GNU/Linux mas reciente desde la siguiente ubicación.

http://www.openni.org/Downloads/OpenNIModules.aspx

Descargar el módulo inestable de NITE

Descargar el módulo inestable de NITE

$ cd ~/kinect

$ tar jxvf nite-bin-linux-x86-v1.5.2.21.tar.bz2

$ cd NITE-Bin-Dev-Linux-x86*/Data

$ chmod a+w *

$ vi *.xml

<License vendor="PrimeSense" key="insert key here"/>
… reemplazar por …
<License vendor="PrimeSense" key="0KOIk2JeIBYClPWVnMoRKn5cdY4="/>

$ cd ..

$ sudo ./install.sh

Probar los ejemplos

Es posible verificar el funcionamiento del software recién instalado con las aplicaciones de demostración que este incluye.  Para hacer esto se recomienda revisar los siguientes directorios.

  1. ~/kinect/OpenNI/Platform/Linux/Bin/x86-Release
  2. ~/kinect/NITE-Bin-Dev-Linux-x86*/Samples/Bin/x86-Debug

Solución de problemas

Verificar el reconocimiento del dispositivo

Una vez conectado el Kinect al puerto USB del computador y a la corriente eléctrica este debe ser reconocido por el sistema operativo.

$ dmesg


[  158.092116] usb 2-3: new high speed USB device number 4 using ehci_hcd

[  158.224738] hub 2-3:1.0: USB hub found
[  158.224915] hub 2-3:1.0: 3 ports detected
[  158.800196] usb 2-3.2: new full speed USB device number 5 using ehci_hcd
[  160.336252] usb 2-3.1: new high speed USB device number 6 using ehci_hcd
[  161.448177] usb 2-3.1: usbfs: USBDEVFS_CONTROL failed cmd mtp-probe rqt 128 rq 6 len 1024 ret -110
[  162.128178] usb 2-3.3: new high speed USB device number 7 using ehci_hcd
[  162.299863] gspca: v2.13.0 registered
[  162.301016] usbcore: registered new interface driver kinect

$ lsusb


Bus 002 Device 005: ID 045e:02b0 Microsoft Corp. Xbox NUI Motor
Bus 002 Device 006: ID 045e:02ad Microsoft Corp. Xbox NUI Audio
Bus 002 Device 007: ID 045e:02ae Microsoft Corp. Xbox NUI Camera

error CS0117: `OpenNI.CalibrationStatus' does not contain a definition for `ManualAbort'

Si se está realizando una actualización de OpenNI probablemente sea buena idea desinstalar los archivos previos antes de realizar nuevamente los pasos descritos en este artículo.

$ sudo rm -rf /usr/include/ni/
$ sudo rm /usr/share/java/org.OpenNI.jar
$ sudo rm /usr/lib/libOpenNI.jni.so
$ sudo rm -rf /usr/lib/mono/gac/OpenNI.net
$ sudo rm /usr/lib/mono/2.0/OpenNI.net.dll
$ sudo rm /usr/lib/libOpenNI.so

Open failed: Failed to set USB interface!


Aparentemente los kernels incluyen un módulo para interactuar con el Kinect que interfiere con la ejecución de OpenNI.  Para verificar esto es necesario ejecutar el siguiente comando.

$ lsmod | grep gspca_kinect

gspca_kinect           12792  0
gspca_main             27610  1 gspca_kinect

En caso de existir este módulo debe ser removido de la siguiente manera.

$ sudo rmmod gspca_kinect

Para evitar permanentemente la carga de este módulo del Kernel es necesario agregarlo a la lista negra de la siguiente manera.

$ sudo vi /etc/modprobe.d/blacklist-kinect.conf

blacklist gspca_kinect

Esta modificación será tenida en cuenta tan pronto como se reinicie el sistema operativo.

Enlaces

  • Módulo Sensor Kinect adaptado por avin2
    https://github.com/avin2/SensorKinect
  • Tagged with:



    En December 25 de 2011, Jorge Iván Meza Martínez escribió acerca de Instalación OpenNI, Sensor Kinect y NITE en GNU/Linux Ubuntu 11.10 desde fuentes.
    Nov 01

    Introducción.

    En criptografía, RSA (Rivest, Shamir y Adleman) es un sistema criptográfico de clave pública desarrollado en 1977. En la actualidad, RSA es el primer y más utilizado algoritmo de este tipo y es válido tanto para cifrar como para firmar digitalmente.

    La seguridad de este algoritmo radica en el problema de la factorización de números enteros. Los mensajes enviados se representan mediante números, y el funcionamiento se basa en el producto, conocido, de dos números primos grandes elegidos al azar y mantenidos en secreto. Actualmente estos primos son del orden de 10200, y se prevé que su tamaño aumente con el aumento de la capacidad de cálculo de los ordenadores.

    Como en todo sistema de clave pública, cada usuario posee dos claves de cifrado: una pública y otra privada. Cuando se quiere enviar un mensaje, el emisor busca la clave pública del receptor, cifra su mensaje con esa clave, y una vez que el mensaje cifrado llega al receptor, este se ocupa de descifrarlo usando su clave privada.

    Se cree que RSA será seguro mientras no se conozcan formas rápidas de descomponer un número grande en producto de primos. La computación cuántica podría proveer de una solución a este problema de factorización.

    Tomado del artículo RSA de Wikipedia.

    Implementación.

    La aplicación de demostración de esta técnica requiere del uso de por lo menos los siguientes namespaces.

    using System;
    using System.IO;
    using System.Security;
    using System.Security.Cryptography;

    Proveedor del servicio de cifrado RSA.

    El núcleo de la implementación es el objeto RSACryptoServiceProvider que realiza las labores de cifrado/descifrado de información.

    public static RSACryptoServiceProvider rsa;

    Establecer los valores iniciales del servicio.

    En este punto se establecen los valores iniciales de configuración del servicio, los cuales son en su mayoría opcionales, y se instancia el objeto mencionado anteriormente.

    const string CONTAINER_NAME = "ContenedorRSA";
    CspParameters cspParams;
    cspParams = new CspParameters(1);	// PROV_RSA_FULL
    cspParams.Flags = CspProviderFlags.UseDefaultKeyContainer;
    cspParams.KeyContainerName = CONTAINER_NAME;
    // Instanciar el algoritmo de cifrado RSA
    rsa = new RSACryptoServiceProvider(cspParams);

    Generar las llaves.

    En esta etapa se crea una pareja de llaves: pública y privada, para las labores de cifrado.  Estas se almacenan por conveniencia en formato XML en los archivos llave_publica.xml y llave_privada.xml correspondientemente.

    // Generar y almacenar la llave pública
    writer = new StreamWriter(@"llave_publica.xml");
    string publicOnlyKeyXML = rsa.ToXmlString(false);
    writer.Write(publicOnlyKeyXML);
    writer.Close();
    // Generar y almacenar la llave privada
    writer = new StreamWriter(@"llave_privada.xml");
    string publicPrivateKeyXML = rsa.ToXmlString(true);
    writer.Write(publicPrivateKeyXML);
    writer.Close();

    Cargar las llaves.

    Una vez que han sido creadas y almacenadas las llaves, estas no deben ser creadas nuevamente.  Para su uso se cargan desde los correspondientes archivos XML y se asocian con el proveedor de cifrado.

    // Cargar y asociar la llave pública al proveedor de cifrado
    StreamReader reader = new StreamReader(@"llave_publica.xml");
    string publicOnlyKeyXML = reader.ReadToEnd();
    rsa.FromXmlString(publicOnlyKeyXML);
    reader.Close();
    // Cargar y asociar la llave privada (y pública) al proveedor de cifrado
    StreamReader reader = new StreamReader(@"llave_privada.xml");
    string publicPrivateKeyXML = reader.ReadToEnd();
    rsa.FromXmlString(publicPrivateKeyXML);
    reader.Close();

    Cifrar la información.

    Para realizar el cifrado de los datos es necesario contar con la llave pública del destinatario.

    cargarLlavePublica();
    // Convertir el texto a cifrar (plano) a su representación en bytse
    byte[] textoPlanoBytes = System.Text.Encoding.UTF8.GetBytes(textoPlano);
    // Realizar el proceso de cifrado
    byte[] textoCifradoBytes = rsa.Encrypt(textoPlanoBytes, false);
    // Convertir el mensaje cifrado a su representación en cadena
    string MensajeCifrado = Convert.ToBase64String(textoCifradoBytes);

    Descifrar la información.

    Para descifrar los datos y obtener el mensaje original es necesario contar con la llave privada del destinatario del mensaje.

    cargarLlavePrivada();
    // Convertir el texto cifrado a su representación en bytse
    byte[] textoCifradoBytes = Convert.FromBase64String(textoCifrado);
    // Realizar el proceso de descifrado
    byte[] textoPlanoBytes = rsa.Decrypt(textoCifradoBytes, false);
    // Convertir el mensaje descifrado a su representación en cadena
    string MensajeDescifrado = System.Text.Encoding.UTF8.GetString(textoPlanoBytes);

    Aplicación de demostración.

    Aplicación de demostración del uso del algoritmo

    Aplicación de demostración del uso del algoritmo RSA

    $ gmcs “/out:RSASample.exe” “/r:/usr/lib/mono/2.0/System.dll” /t:exe “RSASample/Main.cs”

    Enlaces.

    Tagged with:



    En November 1 de 2010, Jorge Iván Meza Martínez escribió acerca de Cifrado y descifrado asimétrico con RSA utilizando C#/Mono.
    Oct 31

    Introducción.

    Advanced Encryption Standard (AES), también conocido como Rijndael (pronunciado “Rain Doll” en inglés), es un esquema de cifrado por bloques adoptado como un estándar de cifrado por el gobierno de los Estados Unidos. El AES fue anunciado por el Instituto Nacional de Estándares y Tecnología (NIST) como FIPS PUB 197 de los Estados Unidos (FIPS 197) el 26 de noviembre de 2001 después de un proceso de estandarización que duró 5 años.  Se transformó en un estándar efectivo el 26 de mayo de 2002. Desde 2006, el AES es uno de los algoritmos más populares usados en criptografía simétrica.

    El cifrador fue desarrollado por dos criptólogos belgas, Joan Daemen y Vincent Rijmen, ambos estudiantes de la Katholieke Universiteit Leuven, y enviado al proceso de selección AES bajo el nombre “Rijndael”.

    Tomado del artículo Advanced Encryption Standard de Wikipedia.

    Implementación con strings.

    La aplicación de demostración de esta técnica requiere del uso de por lo menos los siguientes namespaces.

    using System;
    using System.Security.Cryptography;
    using System.Text;
    using System.IO;

    Establecer la clave y el vector de inicio.

    Estos valores pueden ser especificados manualmente o de manera automática por el framework.  La implementación para permitir que se definan automáticamente estos valores es la siguiente.

    Rijndael rijndael = Rijndael.Create();
    byte[] key = rijndael.Key;
    byte[] iv  = rijndael.IV;

    Es posible forzar la generación de nuevas claves y nuevos vectores de inicio para el algoritmo utilizando los métodos rijndael.GenerateKey() y rijndael.GenerateIV() respectivamente.

    Si por el contrario se desea especificar estos valores manualmente su implementación es la siguiente siendo strKey y strIv, la clave y el vector de inicialización como cadenas de texto.

    byte[] key = UTF8Encoding.UTF8.GetBytes(strKey);
    byte[] iv  = UTF8Encoding.UTF8.GetBytes(strIv);

    Especificando estos valores manualmente es necesario garantizar que sus longitudes sean válidas para el algoritmo.  En este caso se utilizará una longitud de clave de 32 bits y una longitud de vector de inicio de 16 bits.

    int keySize = 32;
    int ivSize = 16;
    Array.Resize(ref key, keySize);
    Array.Resize(ref iv, ivSize);

    Cifrado de cadenas de texto.

    Para cifrar la información se requiere de los siguientes parámetros.

    1. Cadena de texto con los datos a cifrar.
    2. Clave.
    3. Vector de inicio.

    El proceso retornará finalmente una cadena de texto con los datos cifrados.

    /**
     * Cifra una cadena texto con el algoritmo de Rijndael
     *
     * @param	plainMessage	mensaje plano (sin cifrar)
     * @param	Key		        clave del cifrado para Rijndael
     * @param	IV		        vector de inicio para Rijndael
     * @return	string		        texto cifrado
     */
    public static string encryptString(String plainMessage, byte[] Key, byte[] IV)
    {
        // Crear una instancia del algoritmo de Rijndael
        Rijndael RijndaelAlg = Rijndael.Create();
        // Establecer un flujo en memoria para el cifrado
        MemoryStream memoryStream = new MemoryStream();
        // Crear un flujo de cifrado basado en el flujo de los datos
        CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                     RijndaelAlg.CreateEncryptor(Key, IV),
                                                     CryptoStreamMode.Write);
        // Obtener la representación en bytes de la información a cifrar
        byte[] plainMessageBytes = UTF8Encoding.UTF8.GetBytes(plainMessage);
        // Cifrar los datos enviándolos al flujo de cifrado
        cryptoStream.Write(plainMessageBytes, 0, plainMessageBytes.Length);
        cryptoStream.FlushFinalBlock();
        // Obtener los datos datos cifrados como un arreglo de bytes
        byte[] cipherMessageBytes = memoryStream.ToArray();
        // Cerrar los flujos utilizados
        memoryStream.Close();
        cryptoStream.Close();
        // Retornar la representación de texto de los datos cifrados
        return Convert.ToBase64String(cipherMessageBytes);
    }

    Descifrado de cadenas de texto.

    El proceso inverso, el de descifrado, se realiza de manera antagónica.  Para hacerlo es necesario contar con los siguientes parámetros.

    1. Cadena de texto con los datos cifrados.
    2. Clave.
    3. Vector de inicio.

    El proceso retornará finalmente una cadena de texto con los datos descifrados.

    /**
     * Descifra una cadena texto con el algoritmo de Rijndael
     *
     * @param	encryptedMessage	mensaje cifrado
     * @param	Key			clave del cifrado para Rijndael
     * @param	IV			vector de inicio para Rijndael
     * @return	string			texto descifrado (plano)
     */
    public static string decryptString(String encryptedMessage, byte[] Key, byte[] IV)
    {
        // Obtener la representación en bytes del texto cifrado
        byte[] cipherTextBytes = Convert.FromBase64String(encryptedMessage);
        // Crear un arreglo de bytes para almacenar los datos descifrados
        byte[] plainTextBytes = new byte[cipherTextBytes.Length];
        // Crear una instancia del algoritmo de Rijndael
        Rijndael RijndaelAlg = Rijndael.Create();
        // Crear un flujo en memoria con la representación de bytes de la información cifrada
        MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
        // Crear un flujo de descifrado basado en el flujo de los datos
        CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                     RijndaelAlg.CreateDecryptor(Key, IV),
                                                     CryptoStreamMode.Read);
        // Obtener los datos descifrados obteniéndolos del flujo de descifrado
        int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
        // Cerrar los flujos utilizados
        memoryStream.Close();
        cryptoStream.Close();
        // Retornar la representación de texto de los datos descifrados
        return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
    }

    Implementación con archivos.

    El cifrado y descifrado de mensajes en archivos se realiza de manera similar al expuesto anteriormente con cadenas, sin embargo varían los flujos (streams) utilizados para obtener y dirigir el flujo de la información.

    Cifrado a archivos.

    /**
     * Cifra una cadena texto con el algoritmo de Rijndael y lo almacena en un archivo
     *
     * @param	plainMessage	mensaje plano (sin cifrar)
     * @param	filename	        nombre del archivo donde se almacenará el mensaje cifrado
     * @param	Key		        clave del cifrado para Rijndael
     * @param	IV		        vector de inicio para Rijndael
     * @return	void
     */
    public static void encryptToFile(String plainMessage, String filename, byte[] Key, byte[] IV)
    {
        // Crear un flujo para el archivo a generarse
        FileStream fileStream = File.Open(filename, FileMode.OpenOrCreate);
        // Crear una instancia del algoritmo Rijndael
        Rijndael RijndaelAlg = Rijndael.Create();
        // Crear un flujo de cifrado basado en el flujo de los datos
        CryptoStream cryptoStream = new CryptoStream(fileStream,
                                                     RijndaelAlg.CreateEncryptor(Key, IV),
                                                     CryptoStreamMode.Write);
        // Crear un flujo de escritura basado en el flujo de cifrado
        StreamWriter streamWriter = new StreamWriter(cryptoStream);
        // Cifrar el mensaje a través del flujo de escritura
        streamWriter.WriteLine(plainMessage);
        // Cerrar los flujos utilizados
        streamWriter.Close();
        cryptoStream.Close();
        fileStream.Close();
    }

    Descifrado de archivos.

    /**
     * Descifra el contenido de un archivo con el algoritmo de Rijndael y lo retorna
     * como una cadena de texto plano
     *
     * @param	filename		nombre del archivo donde se encuentra el mensaje cifrado
     * @param	Key			clave del cifrado para Rijndael
     * @param	IV			vector de inicio para Rijndael
     * @return	string			mensaje descifrado (plano)
     */
    public static string decryptFromFile(String filename, byte[] Key, byte[] IV)
    {
        // Crear un flujo para el archivo a generarse
        FileStream fileStream = File.Open(filename, FileMode.OpenOrCreate);
        // Crear una instancia del algoritmo Rijndael
        Rijndael RijndaelAlg = Rijndael.Create();
        // Crear un flujo de cifrado basado en el flujo de los datos
        CryptoStream cryptoStream = new CryptoStream(fileStream,
                                                     RijndaelAlg.CreateDecryptor(Key, IV),
                                                     CryptoStreamMode.Read);
        // Crear un flujo de lectura basado en el flujo de cifrado
        StreamReader streamReader = new StreamReader(cryptoStream);
        // Descifrar el mensaje a través del flujo de lectura
        string plainMessage = streamReader.ReadLine();
        // Cerrar los flujos utilizados
        streamReader.Close();
        cryptoStream.Close();
        fileStream.Close();
        return plainMessage;
    }

    Aplicación de demostración.

    La aplicación de demostración incluye los conceptos y el código expuestos en este artículo.  Con ella es posible cifrar y descifrar un mensaje que consiste en una cadena de texto arbitraria en memoria y en un archivo.

    Aplicación de demostración del uso del algoritmo Rijndael

    Aplicación de demostración del uso del algoritmo Rijndael

    Construír la aplicación.

    La aplicación de demostración puede construírse utilizando la solución incluída en la distribución con MonoDevelop o Visual Studio.  También es posible construírla desde línea de comando (Mono) mediante la siguiente instrucción.

    $ gmcs “/out:RijndaelSample.exe” “/r:/usr/lib/mono/2.0/System.dll” /t:exe “RijndaelSample/Main.cs”

    Enlaces.

    Tagged with:



    En October 31 de 2010, Jorge Iván Meza Martínez escribió acerca de Cifrado y descifrado simétrico con Rijndael (AES) utilizando C#/Mono.
    Oct 30

    Introducción.

    Una función de hashing recibe un bloque de datos arbitrarios y genera de manera determinística un arreglo de bytes con el valor de su hash, el cual tiene como característica el ser único para los datos procesados.

    Los valores de hash tienen múltiples usos, entre ellos se utilizan en la criptografía para garantizar que la información de un mensaje no ha sido modificada.  Con este mismo uso, comúnmente se utiliza para determinar si la descarga de archivos ha sido exitosa o no (md5sum).

    Existen varios algortimos de hashing, los mas conocidos son MD5 de 128 bits y SHA1 de 160 bits.  El primero de ellos es muy utilizado actualmente, especialmente para el almacenamiento de contraseñas, sin embargo ya no se considera seguro por lo cual es conveniente utilizar el segundo mencionado.

    Implementación en C#/Mono.

    Para la implementaciones que se describen a continuación se utilizaron los siguientes namespaces.

    using System;
    using System.IO;
    using System.Text;
    using System.Security.Cryptography;

    Calcular el hash de una cadena.

    El primer paso es crear instancias de los algoritmos de hashing.

    HashAlgorithm md5  = HashAlgorithm.Create("MD5");
    HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");

    Posteriormente se calcula el valor del hash de la cadena texto (text) especificada.

    Byte[] md5Data  = md5.ComputeHash(UTF8Encoding.UTF8.GetBytes(text));
    Byte[] sha1Data = sha1.ComputeHash(UTF8Encoding.UTF8.GetBytes(text));

    Finalmente su valor puede ser manipulado o entregado al usuario.

    Console.WriteLine("MD5:  " + BitConverter.ToString(md5Data).Replace("-", ""));
    Console.WriteLine("SHA1: " + BitConverter.ToString(sha1Data).Replace("-", ""));

    Calcular el hash de un archivo.

    El procedimiento es muy similar al cálculo de hash de una cadena, pero a diferencia de este, los datos provienen de un flujo de archivo al cual se le calcula su valor.

    FileStream fs = File.OpenRead(filename);
    md5Data  = md5.ComputeHash(fs);
    sha1Data = sha1.ComputeHash(fs);
    fs.Close ();
    Tagged with:



    En October 30 de 2010, Jorge Iván Meza Martínez escribió acerca de Calculando hashes (MD5 y SHA1) con C#/Mono.
    Oct 22

    Introducción.

    Últimamente he tenido ganas de desarrollar en C# para retomar este lenguaje que tengo un poco abandonado y al mismo tiempo probar los avances que ha tenido el proyecto Mono.  Que mejor inicio que desarrollar una aplicación muy simple para georreferenciar ciudades aprovechando el servicio web de Geonames, esta a su vez me servirá para complementarla y solucionar un problema de información que tengo para otro proyecto.

    Como se podrá apreciar, el código es muy sencillo ya que no utilizo ninguna librería adicional a las estándar, sin embargo es interesante y puede serle de utilidad a alguien mas.

    Cuál es la necesidad ?

    El problema que se tiene es la necesidad de georreferenciar ubicaciones, es decir, conociendo su nombre obtener su ubicación en términos de latitud y longitud.

    Si estoy en Manizales, Caldas, Colombia estaré realmente en latitud 5.07, longitud -75.52056.

    Es necesario tener en cuenta que muchas veces el servicio de georreferenciación retorna múltiples resultados ya que pueden haberse referenciado varios sitios con el mismo nombre, haberse cambiado el nombre de la ubicación o tenerse varios hitos de diferente nivel administrativo.  En Geonames esto último se identifica mediante los campos de características.  Consulte el sitio web de Geonames para mas información acerca de los feature codes.

    Cómo es el servicio web ?

    El servicio web de búsquedas de Geonames recibe una cadena de texto con la ubicación que se desea georreferenciar y retorna una cadena de texto en formato XML (en este caso) con los resultados obtenidos.

    Por ejemplo, la consulta de Manizales, Caldas, Colombia se realizaría a través del siguiente URL.

    http://ws.geonames.org/search?lang=es&type=xml&style=FULL&q=Manizales,Caldas,Colombia

    Retornará el siguiente resultado.

    <geonames style="FULL">
        <totalResultsCount>2</totalResultsCount>
        <geoname>
            <toponymName>Manizales</toponymName>
            <name>Manizales</name>
            <lat>5.07</lat>
            <lng>-75.52056</lng>
            <geonameId>3675443</geonameId>
            <countryCode>CO</countryCode>
            <countryName>Colombia</countryName>
            <fcl>P</fcl>
            <fcode>PPLA</fcode>
            <fclName>city, village,...</fclName>
            <fcodeName>seat of a first-order administrative division</fcodeName>
            <population>357814</population>
            <alternateNames>Manisales,Manisalesas,Manizales,Манисалес</alternateNames>
            <elevation/>
            <continentCode>SA</continentCode>
            <adminCode1>37</adminCode1>
            <adminName1>Caldas</adminName1>
            <adminCode2/>
            <adminName2/>
            <alternateName lang="en">Manizales</alternateName>
            <alternateName lang="pl">Manizales</alternateName>
            <alternateName lang="lt">Manisalesas</alternateName>
            <alternateName lang="bg">Манисалес</alternateName>
            <alternateName lang="cs">Manizales</alternateName>
            <alternateName lang="link">http://en.wikipedia.org/wiki/Manizales</alternateName>
            <alternateName lang="de">Manizales</alternateName>
            <alternateName lang="sv">Manizales</alternateName>
            <alternateName lang="es">Manizales</alternateName>
            <alternateName lang="no">Manizales</alternateName>
            <alternateName lang="pt">Manizales</alternateName>
            <timezone dstOffset="-5.0" gmtOffset="-5.0">America/Bogota</timezone>
            <score>1.0</score>
        </geoname>
        <geoname>
            <toponymName>Manizales</toponymName>
            <name>Manizales</name>
            <lat>5.08333</lat>
            <lng>-75.5</lng>
            <geonameId>3675444</geonameId>
            <countryCode>CO</countryCode>
            <countryName>Colombia</countryName>
            <fcl>A</fcl>
            <fcode>ADM2</fcode>
            <fclName>country, state, region,...</fclName>
            <fcodeName>second-order administrative division</fcodeName>
            <population/>
            <alternateNames/>
            <elevation/>
            <continentCode>SA</continentCode>
            <adminCode1>37</adminCode1>
            <adminName1>Caldas</adminName1>
            <adminCode2>3675444</adminCode2>
            <adminName2>Manizales</adminName2>
            <timezone dstOffset="-5.0" gmtOffset="-5.0">America/Bogota</timezone>
            <score>0.3448537290096283</score>
        </geoname>
    </geonames>

    Finalmente la tarea de la aplicación que consuma el servicio será procesar el documento XML y obtener la información que necesite.

    Cómo es la implementación ?

    Las librerías (namespaces) utilizados son los siguientes.

    using System;
    using System.Net;
    using System.Text;
    using System.Xml;
    using System.Collections.Generic;

    Se prepara el URL para consumir el servicio con la ubicación a geocodificar.  En este caso, especifico una por defecto si no suministra una.

    string location = (args.Length == 0) ? "Manizales, Caldas, Colombia" : args[0];
    string url = "http://ws.geonames.org/search?lang=es&type=xml&style=FULL&q=" + location;

    Se consume el servicio web y se obtiene la cadena de texto con la respuesta en formato XML.

    WebClient client = new WebClient();
    string xml = client.DownloadString(url);

    Se crea un objeto para manipular el documento XML recién recibido, se obtienen los nodos relacionados con la respuesta de la georreferenciación (geoname)  y se verifica que haya registros, de lo contrario no habrá nada que hacer.

    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml);
    XmlNodeList geonames = doc.GetElementsByTagName("geoname");
    if(geonames.Count == 0)
     throw new Exception("There is no geonames in the result!");
    else
     Console.WriteLine("I found " + geonames.Count + " places!\n");
    

    Se recorren los resultados obtenidos extrayéndoles la información georreferenciada que se requiera.

    foreach(XmlElement place in geonames)
    {
     Console.WriteLine("* LUGAR: " + place["name"].InnerText + "\n");
     Console.WriteLine("\tNombre: "          + place["name"].InnerText);
     Console.WriteLine("\tDepartamento: "    + place["adminName1"].InnerText);
     Console.WriteLine("\tLatitud: "         + place["lat"].InnerText);
     Console.WriteLine("\tLongitud: "        + place["lng"].InnerText);
     Console.WriteLine("\tPaís: "            + place["countryName"].InnerText +
                       " (" + place["countryCode"].InnerText + ")");
     Console.WriteLine("\tPoblación: "       + place["population"].InnerText + " habitantes");
     Console.WriteLine("\tPaís: "            + place["countryName"].InnerText +
                       " (" + place["countryCode"].InnerText + ")");
     Console.WriteLine("\tCaracterísticas: " + place["fcl"].InnerText + "/" + place["fcode"].InnerText +
                       "> " + place["fclName"].InnerText + " (" + place["fcodeName"].InnerText + ")");
     Console.WriteLine();
    }
    

    Cómo construyo el programa ?

    Si se utiliza VisualStudio/MonoDevelop sólo es necesario abrir la solución (incluída en el paquete de demostración) y ejecutar el comando de Build o Run del menú.

    Si se desea realizar manualmente deberá ejecutarse un comando como el siguiente.

    $ gmcs "/out:GeoCoderSimple.exe" "/r:/usr/lib/mono/2.0/System.dll" "/r:/usr/lib/mono/2.0/System.Xml.dll" /t:exe "geonames_search_raw/Main.cs"

    Donde geonames_search_raw/Main.cs es el código fuente de la aplicación y GeoCoderSimple.exe será el archivo binario resultante.

    Cómo ejecuto el ejemplo ?

    Ya sea invocándolo desde el IDE o desde línea de comando, el programa recibe un argumento.  En caso de obviarse este argumento se utilizará el valor por defecto.

    $ ./GeoCoderSimple.exe

    I found 2 places!
    * LUGAR: Manizales
     Nombre: Manizales
     Departamento: Caldas
     Latitud: 5.07
     Longitud: -75.52056
     País: Colombia (CO)
     Población: 357814 habitantes
     País: Colombia (CO)
     Características: P/PPLA> city, village,... (seat of a first-order administrative division)
    * LUGAR: Manizales
     Nombre: Manizales
     Departamento: Caldas
     Latitud: 5.08333
     Longitud: -75.5
     País: Colombia (CO)
     Población:  habitantes
     País: Colombia (CO)
     Características: A/ADM2> country, state, region,... (second-order administrative division)
    

    Enlaces.

    Tagged with:



    En October 22 de 2010, Jorge Iván Meza Martínez escribió acerca de Georreferenciando de manera fácil y simple con GeoNames utilizando C#/Mono.
    Aug 02

    Introducción.

    OpenSimulator es un servidor de aplicaciones 3D que puede ser utilizado para crear ambientes o mundos virtuales los cuales pueden ser accedidos a través de una variedad de clientes y  protocolos. Permite realizar los desarrollos con las tecnologías mas habituales gracias a un diseño flexible, fácilmente extendible mediante módulos cargables para crear con ellos configuraciones completamente personalizadas.  Este software se licencia bajo la BSD License, lo que permite que sea incluído en paquetes de código abierto o comerciales.   Por defecto, OpenSimulator puede simular un entorno virtual de Second Life™ (incluyendo la compatibilidad con su cliente). Otros ambientes, protocolos y características pueden ser soportadas mediante módulos añadidos.

    Tomado de http://opensimulator.org/.

    Instalar Mono.

    # pacman -S mono unzip

    # mono --version

    Mono JIT compiler version 2.6.7 (tarball Sun Jul 25 19:50:39 CEST 2010)
    Copyright (C) 2002-2010 Novell, Inc and Contributors. www.mono-project.com
    TLS:           __thread
    GC:            Included Boehm (with typed GC and Parallel Mark)
    SIGSEGV:       altstack
    Notifications: epoll
    Architecture:  amd64
    Disabled:      none

    # vi /etc/rc.conf

    DAEMONS=(... mono)

    Crear usuario opensim.

    # /usr/sbin/useradd -m -g users -s /bin/bash -c “OpenSimulator” opensim

    # passwd -l opensim

    Instalar OpenSim.

    # wget http://dist.opensimulator.org/opensim-0.7-bin.tar.gz

    # tar zxvf opensim-0.7-bin.tar.gz

    # mv opensim-0.7-bin /home/opensim/0.7

    # chown -R opensim:users /home/opensim/0.7

    # ln -s /home/opensim/0.7 /opt/opensim

    Iniciar OpenSim.

    # su -c /opt/opensim/bin/opensim-ode.sh opensim

    Configurar OpenSim por primera vez.

    =====================================
    We are now going to ask a couple of questions about your region.

    You can press ‘enter’ without typing anything to use the default

    the default is displayed between [ ]: brackets.
    =====================================

    New region name []: Playing Region
    Region UUID [18d5fc00-1452-4876-bb46-6f75c06387a6]:
    Region Location [1000,1000]:
    Internal IP address [0.0.0.0]:
    Internal port [9000]:
    Allow alternate ports [False]:
    External host name [SYSTEMIP]:

    Your region is not part of an estate.
    Do you wish to join an existing estate? [no]:
    New estate name [My Estate]: Playing Estate

    The current estate has no owner set.
    Estate owner first name [Test]: Master
    Estate owner last name [User]: Player
    Password: testing
    Email []:

    Enlaces.

    Tagged with:



    En August 2 de 2010, Jorge Iván Meza Martínez escribió acerca de Instalar OpenSim 0.7 en ArchLinux 2010.05 x64.
    Feb 24

    Una forma para realizar comunicación entre los prims internos de OpenSimulator o Second Life y el mundo externo es a través del uso de XML-RPC el cual permite enviar mensajes a un objeto dentro de una región, siempre y cuando este se haya registrado para recibir dicha comunicación.

    Crear Script para Recibir Datos :

    • Abrir nuestro visor favorito y entrar al servidor de OpenSimulator o SecondLife
    • Crear un objeto
    • Adicionar un Script
    • Abrir el script
    • Colocar el siguiente codigo :
      default {
         state_entry()
         {
            llOpenRemoteDataChannel();
         }
      
         remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) {
            if(type == REMOTE_DATA_CHANNEL) {
               llOwnerSay("Canal : " + (string) channel + "");
            }
            else if(type == REMOTE_DATA_REQUEST) {
               llRemoteDataReply(channel,NULL_KEY,"Exito",1221);
               llOwnerSay("Cadena : " + sval + "nNumero: " + (string) ival);
            }
            else {
               llOwnerSay("Error");
            }
         }
      }
    • Guardar
    • En este momento el servidor debe compilar el script y muestra en el chat :
      [11:54]  Compile successful
      [11:54]  Primitive: Canal : 61b5e9ca-9378-4254-af36-d78d6ed839de
    • La cadena : 61b5e9ca-9378-4254-af36-d78d6ed839de es el identificador del canal por el cual escucha el prim, es diferente para cada prim

    Enviar Datos con C# :

    Se utilizara la libreria XmlRpcCS para realizar la comunicación entre la aplicación y el objeto en OpenSimulator o SecondLife.

    • Abrir una consola
    • Crear el directorio para el cliente
      mkdir clientxmlrpc
    • Cambiar al directorio
      cd clientxmlrpc
    • Copiar la libreria al directorio actual
      cp ../XmlRpcCS/XmlRpcCS.dll .
    • Crear un archivo Client.cs y adicionamos el siguiente codigo :
      using System.Collections;
      using Nwc.XmlRpc;
       
      public class Client {
              public static void Main() {
                      // Informacion del Servidor de Second Life
                      // Canal por donde escucha el cliente
                      string server = "http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi";
                      string channel = "eafc58de-5d8a-364e-d6d8-4c4cab0129f4";
       
                      // Parametros
                      Hashtable args = new Hashtable();
                      args.Add("Channel",channel);
                      args.Add("IntValue",12345);
                      args.Add("StringValue","Hello World!"); 
       
                      // Cliente XMLRPC
                      XmlRpcRequest request = new XmlRpcRequest();
                      request.MethodName = "llRemoteData";
                      request.Params.Add(args);
       
                      // Invocacion y Resultado
                      Hashtable ret = (Hashtable) request.Invoke(server);
                      System.Console.WriteLine(ret["StringValue"]);
                      System.Console.WriteLine(ret["IntValue"]);
              }
      }
    • Compilamos el codigo :
      gmcs -lib:. -r:XmlRpcCS.dll Client.cs
    • Ejecutamos
      mono Client.exe
    • Debe mostrar en pantalla los valores enviados por el objeto
      Exito
      1221
    • Mienstras tanto en OpenSimulator debe aparecer en el chat la informacion enviada
      Hello World!!! 12345

    Para usar el mismo codigo con OpenSimulator la cadena server debe tener la direccion de nuestro servidor : http://<ipServidor>:<puerto>/cgi-bin/xmlrpc.cgi

    Enlaces :

    Tagged with:



    En February 24 de 2009, Marlon J. Manrique escribió acerca de Cliente XML-RPC en Mono para OpenSimulator.
    Feb 24

    Actualmente algunos sistemas como OpenSimulator o Second Life utilizan servicios remotos basados en XML-RPC, por tal motivo es necesario utilizar una libreria para realizar los llamados a estos servicios, actualmente para Microsoft .NET podemos encontrar dos librerias :

    Utilizaremos la libreria XmlRpcCS, la cual es utilizada por el proyecto OpenSimulator para implementar el servicio de XMLRPC que permite realizar llamados remotos a objetos en este mundo virtual.

    Requerimientos :

    • Debemos instalar lo paquetes para compilar la libreria
      sudo apt-get install nant mono-2.0-devel libmono-winforms2.0-cil mono-1.0-devel

    Construcción de la Libreria :

    • Abrir una consola
    • Descargar la ultima versión de la libreria
      http://sourceforge.net/project/platformdownload.php?group_id=123702
    • Por ejemplo la versión 1.10
      wget http://ufpr.dl.sourceforge.net/sourceforge/xmlrpccs/XmlRpcCS-1.10.zip
    • Descomprimir el archivo
      unzip XmlRpcCS-1.10.zip
    • Cambiar al directorio de la libreria
      cd XmlRpcCS
    • Compilar la libreria
      nant
    • El archivo XmlRpcCS.dll es creado

    Enlaces :

    Tagged with:



    En February 24 de 2009, Marlon J. Manrique escribió acerca de Libreria XML-RPC para Mono.
    Dec 07

    Despues de compilar la libreria de linopenmetaverse me dedique hacer el primer programa con la libreria, donde un avatar se autentique con el servidor y permanezca en el mundo un determinado tiempo y despues salga de este, esto con el fin de conocer el uso de la libreria y los pasos requeridos para compilar el programa.

    Al principio solo dejaba al avatar cinco segundos en el mundo, pero al tratar de entrar de nuevo el servidor me sacaba diciendo que el avatar ya estaba logueado, entonces probe con 60 segundos, 30 segundos, al final me quede con 15 segundos asegurando asi que el proceso de autenticacion y loqueo se cumpla totalmente, para luego proceder a cerrar la conexion.

    • Abrir una consola
    • Crear el directorio para nuestro programa
      mkdir MyBot
      cd MyBot
    • Copiar las dlls necesarias de la libreria libopenmetaverse compiladas anteriormente
      cp <directorio libopenmv>/trunk/bin/OpenMetaverse.dll .
      cp <directorio libopenmv>/trunk/bin/OpenMetaverseTypes.dll .
      cp <directorio libopenmv>/trunk/bin/OpenMetaverse.StructuredData.dll .
      cp <directorio libopenmv>/trunk/bin/log4net.dll .
    • Crear el programa en C#
      vi MyBot.cs
      using System;
      using System.Threading;
      using OpenMetaverse; // Libreria de Acceso OpenSimulator
       
      public class MyBot
      {
              public static void Main()
              {
                      // Crear cliente
                      GridClient client = new GridClient();
       
                      // Informacion acerca del avatar y la aplicacion
                      LoginParams loginParams =
                               client.Network.DefaultLoginParams(
                                      "Juan","Perez","1234","MyBot","0.1");
       
                      // Colocamos la direccion de nuestro simulador
                      loginParams.URI = "http://192.168.1.3:9000/";
       
                      // Tratamos de entrar
                      if(client.Network.Login(loginParams))
                      {
                              // Si entramos sacamos un mensaje,
                              // esperamos 15 segundos
                              // y salimos del mundo
                              Console.WriteLine("Entrando ...");
                              Thread.Sleep(15000);
                              client.Network.Logout();
                      }
                      else
                              // Si no fue posible loguearse, mostrar error
                              Console.WriteLine(client.Network.LoginMessage);
              }
      }
    • Compilar el programa :
      gmcs -lib:. -r:OpenMetaverse.dll MyBot.cs
    • Ejecutar el programa :
      mono MyBot.exe

    Para verificar que esto esta funcionando puede abrir el visor y entrar con un usuario a la zona inicial de la region, cuando ejecute el programa Juan Perez aparecera por unos momentos.

    Tagged with:



    En December 7 de 2008, Marlon J. Manrique escribió acerca de Creando el Primer Bot con LibOpenMetaverse.
    Dec 07

    Para comenzar a desarrollar con la libreria libsecondlife, tome la decision de mejor pasarme de una vez a libopenmetaverse, no encontre binarios disponibles asi que me di a la tarea de compilar la libreria.

    Preparativos :

    • Abrir una terminal
    • Debemos instalar el cliente de subversion para poder descargar los fuentes del repositorio
      sudo apt-get install subversion
    • Debemos instalar lo paquetes para compilar la libreria
      (He instalado ya tantos paquetes de mono que la verdad no se con cuales es lo minimo)
      sudo apt-get install nant mono-2.0-devel libmono-winforms2.0-cil mono-1.0-devel

    Compilar LibOpenMetaverse :

    • Descargar la version actual de la libreria por medio de subversion
      svn co http://openmetaverse.org/svn/omf/libopenmetaverse/trunk/
    • Ir al directorio trunk
      cd trunk
    • Ejecutar un shell que prepara el proyecto y lo compila
      sh runprebuild.sh nant
    • Aqui tenemos un problema, el script lanza el siguiente error :
      [: 11: ==: unexpected operator
      [: 18: ==: unexpected operator
      Parece ser que el shell no entiende los operadores ==
    • Para corregir esto ejecutamos con el shell bash
      bash runprebuild.sh nant
    • Los binarios de la libreria esta en el directorio bin
    Tagged with:



    En December 7 de 2008, Marlon J. Manrique escribió acerca de Compilando LibOpenMetaverse en Ubuntu 8.10.