viernes, 10 de julio de 2015

Comer sockets

Del libro del Sr. Comer sobre Internetworking with TCP/IP se puede encontrar un ejemplo de la utilización de Sockets. También es válido para comunicación entre procesos IPC.
He aquí los dos archivos para el ejemplo:



 /*whoisclient.c -main */  
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <sys/types.h>  
 #include <sys/socket.h>  
 #include <netinet/in.h>  
 #include <netdb.h>  
 /*_________________________________________________________________  
  * Program: whoisclient  
  *  
  *Purpose: UNIX application program thar becomes a client for the  
  *       Iternet "whois" services.  
  *  
  *Use:   whois hostname username  
  *  
  *__________________________________________________________________  
  */  
 main (argc,argv)  
 int argc;          /*standard UNIX argument declarations */  
 char *argv[];  
 {  
   int s;              /*socket descriptor           */  
   int len;               /*length of received data          */  
   struct sockaddr_in sa;     /*Internet socket addr, structure     */  
   struct hostent *hp;          /*result of host name lookup          */  
   struct servent *sp;          /*result of service lookup          */  
   char *myname;          /*pointer to name of this program     */  
   char *host;               /*pointer to mte host name          */  
   char *user;               /*ponter to mte user name          */  
   myname = argv[0];  
   char buf[BUFSIZ+1];  
   /*  
   * Check that there are two command line arguments  
   */  
 if(argc != 3){  
      fprintf(stderr,"Usage: %s host username\n", myname);  
      exit(1);  
 }   
 host = argv[1];  
 user = argv[2];  
 /*  
  * Look up the specified hostname  
  */  
 if((hp = gethostbyname(host)) == NULL) {  
      fprintf(stderr, "%s: %s: no such host?\n", myname, host);  
      exit(1);  
 }  
 /*  
  * Put host's addres and address type into socket structure  
  */  
 bcopy((char *)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);  
 sa.sin_family = hp->h_addrtype;  
 /*  
  * Look up the socket number for the WHOIS service  
  */  
 if((sp = getservbyname("whois","tcp")) == NULL ){  
      fprintf(stderr,"%s: No whois service on this host\n", myname);  
      exit(1);  
 }  
 /*  
  * Put the whois socket number into the socket structure  
  */  
 sa.sin_port = sp->s_port;  
 /*  
  * Allocate an open socket  
  */  
 if ((s = socket(hp->h_addrtype, SOCK_STREAM,0)) < 0 ){  
      perror("socket");  
      exit(1);  
 }  
 /*  
  * Connect to the remote server ahora (struct sockaddr*)  antes &sa  
  */  
 if(connect(s, (struct sockaddr*)&sa , sizeof(sa)) < 0){  
      perror("connect");  
      exit(1);  
 }  
 /*  
  * Send the request  
  */  
 if(write(s, user, strlen(user)) != strlen(user)){  
      fprintf(stderr, "%s: write error\n", myname);  
      exit(1);  
 }  
 /*  
  * Read the reply and put to user's output  
  */  
 while( (len =read(s, buf, BUFSIZ)) > 0)  
      write(1, buf, len);  
 close(s);  
 exit(0);  
 }  


Y aquí el servidor.

 /* whoisserver.c - main */  
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <sys/types.h>  
 #include <sys/socket.h>  
 #include <netinet/in.h>  
 #include <netdb.h>  
 #include <pwd.h>  
 /*______________________________________________________________  
  * Program:      whoisserver  
  *   
  * Purpose:   UNIX application program that acts as a server for   
  *          the "whois" service on the local machine. It listens  
  *          on well-known WHOIS port (43) and anwers queries from  
  *          client. This program requires super-user privilege to   
  *          run.  
  * Use:      whois hostname username  
  *  
  *______________________________________________________________________  
  */  
 #define BACKLOG   5                     /* # of requests we're willing to queve */  
 #define MAXHOSTNAME 32                    /* maximum host name length we tolerate */  
 main(argc, argv)  
      int argc;                    /* standard UNIX argument declarations */  
      char *argv[];  
 {  
      int s, t;                    /*socket descriptors               */  
      int i;                         /*general purpose integer          */  
      struct sockaddr_in sa, isa;          /*Internet socket structure          */  
      struct hostent *hp;               /*result of host name lookup          */  
      char *myname;                    /*pointer to name of this program     */  
       struct servent *sp;               /*result of service lookpup          */  
      char localhost[MAXHOSTNAME+1];      /*local host name as character string  */  
      myname = argv[0];  
      /*  
       * Look up the WHOIS service entry  
       */  
      if ((sp = getservbyname("whois", "tcp")) == NULL) {  
           fprintf(stderr, "%s: No whois service on this host\n", myname);  
           exit(1);  
      }  
      /*  
       * Fet our own host information  
       */  
      gethostname(localhost, MAXHOSTNAME);  
      if((hp = gethostbyname(localhost)) == NULL){  
           fprintf(stderr, "%s: cannot get local host info?\n", myname);  
           exit(1);  
      }  
      fprintf(stderr,"localhost: %s \n", localhost); /*BARROS */  
      /*  
       * Put the WHOIS socket number and our addres info  
       * into the socket structure  
       */  
      sa.sin_port = sp->s_port;  
      bcopy((char *)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);  
      sa.sin_family = hp->h_addrtype;  
      /*   
       * Allocate an open socket for incoming connections  
       */  
      if((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {  
           perror("socket");  
           exit(1);       
      }  
      /*  
       * Bind the socket to the service port  
       * so we hear incoming connections  
       */  
      if(bind(s, (struct sockaddr*)&sa, sizeof sa) < 0) {  
           perror("bind");  
           exit(1);  
      }  
      /*  
       * Set maximum connections we will fall behind  
       */  
      listen(s, BACKLOG);  
      /*  
       * Go into an infinite loop waiting far new connections  
       */  
      while(1) {  
           i = sizeof isa;  
           fprintf(stderr,"i isa: %d , puerto %d , dirección %d\n", i, isa.sin_port, isa.sin_addr.s_addr); /*BARROS */  
           /*   
            * We hang in accept() while waiting for new customers  
            */  
           if((t = accept(s, (struct sockaddr*)&isa, &i)) < 0) {  
                perror("accept");  
                exit(1);  
           }  
           whois(t);               /* perform the actual WHOIS service */  
           close(t);  
      }  
 }  
      /*  
       * Get the WHOIS request from remote host and format a reply.  
       */  
      whois(sock)  
      int sock;  
 {  
      struct passwd *p;  
      char buf[BUFSIZ+1];  
      int i;  
      /*  
      * Get one line request  
       */  
      if((i =read(sock, buf, BUFSIZ)) <= 0)  
           return;  
      buf[i] = '\0';                    /* Null terminate */  
      /*  
        * Look up the requested user and format reply  
       */  
      if((p = getpwnam(buf)) == NULL)  
           strcpy(buf,"User not found\n");  
      else  
           sprintf(buf, "%s: %s\n", p->pw_name, p->pw_gecos);  
      /*  
        * Return reply  
       */  
      write(sock, buf, strlen(buf));  
      return;  
 }  

viernes, 19 de junio de 2015

De los datos libres

Las ideas no nos pertenecen, los dueños son los que en realidad las realizan. Recuerdo alguna vez que conversaba con un amigo sobre nuestras grandiosas ideas, ideas para cambiar el mundo e impactar de verdad en la historia y comodidad de la humanidad. Al finalizar la charla constatamos que no importa lo grandiosas que sea nuestras ideas, en realidad no habíamos hecho nada.

Viajado y viviendo en el extranjero uno se pregunta sobre por qué ellos sí y por qué nosotros no, sobre muchos temas.  Y es así que comenzamos a trabajar sobre servicios que explotan la información existente para mejorar la calidad de los servicios que la gente requiere.  Una idea que da vueltas hace mucho tiempo es la de poseer información sobre el paso de las unidades de transporte público por determinada parada.  Tecnología que existe hace mucho tiempo en otros lugares y que en mi ciudad es toda una pesadilla para dar un paso hacia adelante. Ver por ejemplo que existe un planificador de viaje como el presentado por www.tisseo.fr que nos permite especificar la hora de partida o de llegada, y nos muestra varias posibilidades permutando las líneas de transporte existentes; y comparar eso con mi ciudad en donde ni siquiera las rutas de los buses se pueden encontrar en Internet.

Es por eso que decidí tratar de utilizar mis conocimientos para proporcionar una solución a este problema.
Se trata de un sistema que permite enlazar un punto de partida y otro de llegada mediante varias de las líneas de transporte existente.

PASOS
1. Obtener datos (geometría) de las calles por donde pasan los buses.
2. Generar la geometría de las líneas de transporte. Una línea pasa por una secuencia de calles, en teoría podemos armar la ruta completa basados en las calles y sus intersecciones.
3. Generar el sistema recomendador  que se basa en la líneas existentes.
4. Refinar el problema mediante la agregación de restricciones adicionales como horarios de pasada, desvíos, y retardos.

AVANCE
1. Obtener la geometría.
Varias instituciones del gobierno han utilizado recursos para generar información cartográfica de la ciudad. El acceso a esta información es difícil y esta sujeto a gran cantidad de procesos burocráticos. Pero, sabemos que la información esta presentada utilizando un servidor ArcIMS. Este servidor permite publicar imágenes de mapas con un formato propietario, como si se tratará de un servicio Web Map Service (WMS) o Web Features Service (WFS).

Se debe enviar una petición post al host que alberga el servidor ArcIMS.
POST /servlet/com.esri.esrimap.Esrimap?ServiceName=nombreServicio&CustomService=Query&ClientVersion=4.0&Form=True&Encode=False

Se debe revisar el tipo de objeto ARCXML que se envía al servidor.
Por ejemplo una petición es:

"< arcxml version="1.1">
    < request>
        < get_features checkesc="true" envelope="false" featurelimit="25" geometry="false" outputmode="xml">
        < layer id="10">
        < spatialquery subfields="NOMENCLATU NOMBRE_APE">
           
               
           

        < /spatialquery>
        < /layer>< /get_features>
    < /request>"

Y una respuesta que llega sobre HTTP es:

"< arcxml version="1.1">

  < features>
    < feature>
      < fields nombre_ape="DIEZ DE AGOSTO" nomenclatu="LS-29">
    < /fields>< /feature>
  < featurecount count="1" hasmore="false">
  < /featurecount>< /features>< /response>"
Con estos mecanismos, se desarrolla un programa que se encarga de recoger las calles de la ciudad.

Postgres

psql
\connect nombrebd


ST_Distance(geometry g1, geometry g2);


SELECT ST_Distance(
    ST_Transform(ST_GeomFromText('POINT(-72.1235 42.3521)',4326),32717),
    ST_Transform(ST_GeomFromText('LINESTRING(-72.1260 42.45, -72.123 42.1546)', 4326),32717)
  );
st_distance
en metros 
 
 
# SELECT PostGIS_version();
            postgis_version            
---------------------------------------
 2.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
(1 row)
 

lunes, 25 de mayo de 2015

Maratón ACSAM 2015

La consultora ACSAM lleva años realizando la ultramaratón (Biblian - Santa isabel)y maratón de Cuenca. Hasta donde tengo entendído la inscripción es gratuita, pero se debe hacer con algún tiempo antes de la fecha de la carrera.
Entonces se tienen carreras muy grandes (100 y 42 km) y gratuitas y del otro lado se tiene las nuevas carreras más cortas (3 - 5 - 10 km) pero que son mucho más caras (10 a 25 dolares).
Bajo la lógica de la distancia la maratón debería costar como 40 o 100 dólares.
En las carreras pagadas se obtiene:
- Camiseta gratis con mucha publicidad: la idea no es dotar al participante de una prenda de calidad pero tratar de "colocar una marca" a los ojos de las personas que observan la camiseta.
-  Una medalla, pese a que no se llegue en los primeros lugares, es necesario dar a las personas un incentivo para seguir compitiendo; no basta con cambiar hacia un estilo de vida más saludable. Y para almacenar basura en la casa de uno.
- Espectáculo con tarimas y artistas, como si fuera necesario entretener a la gente, se trata de una carrera no de un show.
- Rifa de premios: pues no es suficiente con realizar una actividad física, se debe vender otras ilusiones a las personas que pagan muy caro por su participación.

Como ejemplo tenemos la carrera de las Cruces, la carrera debe ser corrida la noche de la víspera del día de la cruz (3 de mayo). Sin importar si se trata de un lunes o martes o día que fuere. Así era la tradición. Ahora al tener una alianza entre una compañía de Marketing y los organizadores de la competencia el precio de 1 o 2 dólares subió a 10, so pretexto de hacerlo un fin de semana, durante el día, "regalando" camiseta, y con un show al terminar la competencia.

Es mi opinión que es mejor, correr como manda la tradición, es decir el día que corresponda, con un valor mucho más bajo y sin ridiculeces.
ACSAM lo ha demostrado sin bla bla y con el ejemplo, una carrera hecha con corazón y para los participantes, gratuita, y con el solo fin de promocionar el deporte, tan necesario en una sociedad de fofos que ya no hacen ejercicio.

Reflexionemos un poco sobre los costos actuales desembolsados tan solo por correr.  Creo que solo es necesario contar con un equipo de personas que controle y bloquee a los autos durante el circuito. El maratón de ACSAM ha venido proporcionando cronometraje con chip RFID desde hace algunos años, entonces por qué pagas tanto??

lunes, 11 de mayo de 2015

Miercoles de Frances Urco

Como parte del aprendizaje de la lengua francesa, recibía información sobre charlas que de alguna manera relacionen a Francia con el Ecuador.
En una ocasión asistí a una conferencia en el actual museo de arte moderno (plaza de San Sebastian) en Cuenca. Se trataba de un ex presidente del banco central, en esos momentos recidía en Francia y conformaba algun grupo en la UNESCO.  La charla contaba historias relacionadas con el paso de la misión geodésica por Ecuador y por Cuenca.

Contaba pues, que al llegar la misión a Guayas a una latitud sur muy cercana al ecuador del planeta, el grupo se divió en dos. Una parte buscaría el ecuador desde la costa (dirección norte, hacia Esmeraldas) y la otra parte seguiría el camino normal hasta Quito para en sus alrededores realizar la medida del ecuador (latitud cero).

Luego de determinar bien el ecuador, se realizarían otras medidas en el eje longitudinal, sirviéndose de elementos colocados en lo alto de algunas montañas.  Es decir, que durante esas campañas de medición se levantaron varios teodolitos en las montañas de los Andes ecuatorianos. Y es así que cerca de Cuenca, en Tarqui, lugar de la batalla del mismo nombre entre el Perú y la Gran Colombia, se levantó este punto para medir.

Como dato interesante, ahora la montaña se conoce como frances-Urco, urco viene de urcu del kichwa que significa montaña. Bueno, y frances, porque los franceses colocaron allí un teodolito.
Asi mismo, es curioso encontrar personas de tes muy blanca y ojos de color poco comunes en los alrededores, posiblemente por que algunos decidieron quedarse a vivir por acá. y de la misma forma nombres con orígenes variados como Corinna (típico aleman).

Con los años y pese a la proximidad, nunca había visitado este lugar hasta hace poco con un grupo de corredores de trail. El trail es correr por senderos montañosos y no tan planos.



Ver mapa más grande

Como se puede ver en el mapa, existe un sendero de color azul, el mismo que pasa por una cuchilla de montaña y permite llegar al sitio del teodolito.  Les recomiendo hacer la ruta ya sea corriendo o en bicicleta de montaña.
Y si tienen ganas de saber más sobre la misión geodesica en su paso por el país, les recomiendo el libro en español o en frances sobre el tema.

lunes, 4 de mayo de 2015

ANT+ plugin sampler

Como se indicó en una entrada anterior, deseamos utilizar un estandar de comunicación de bajo consumo para redes sin cable de area personal para una aplicación aún desconocida (LPWPAN).

Se puso apunto el entorno de desarrollo en una computadora X. SDK android y Netbeans con el plugin NB-Android.
1. El primer intento consistía en sólo ocupar el código necesario para recolectar datos del lector de frecuencia cardiaca de marca GARMIN junto con un teléfono inteligente con soporte de ese estandard. Habíamos instalado las aplicaciones S-life para Samsung Galaxy S4 y "ANT+ plugin sampler" para la gama de los sony Xperia Zx.  Los programas corren bien y permiten recolectar o presentar los datos directamente en el teléfono.
2. El segundo paso consiste en encontrar código fuente para poder nosotros mismo manipular el comportamiento del programa.  Para por ejemplo enviar los datos recolectados a un servidor remoto o para realizar algún cálculo.

Para completar el segundo paso se utilizó un segmento de código mínimo pero no lo logramos compilar. Es por eso que tratamos de hacer correr el código dado por ANT+ y luego iremos retirando los segmentos de código no necesarios.

Se generó un ejecutable que no se instalaba en el dispositivo de prueba. Pero no se daba mayor detalle sobre las razones para no poder instalar la aplicación.
El SDK de Android tiene un programa que ayuda a depurar los ejecutables para esa plataforma mediante el cable USB.

Al conectar el dispositivo y ejecutar un adb (se debe habilitar la depuración por USB): y si se trata de Xperia presionar en "about device", y luego 7 veces en número de compilación para convertirse en desarrollador.
 android-sdk-linux/platform-tools$ ./adb -d devices
List of devices attached
????????????    no permissions


Para los permimos buscar en internet como modificar udev
Si logramos solventar este problema probablemente aparezcan otros como por ejemplo:
android-sdk-linux/platform-tools$ ./adb -d devices
List of devices attached
BH90UXUK1L    unauthorized


Ya vamos mejorando, ahora solo estamos des autorizados. para solucionarlo se debe buscar en internet y seguir los pasos para que la conexión se haga correctamente.
Buscar soluciones hasta que se muestre de la siguiente manera:
android-sdk-linux/platform-tools$ ./adb devices
List of devices attached
BH90UXUK1L    device


Desde NetBeans se puede lanzar ya la aplicación directamente en el dispositivo.
Bueno no siempre.  Se nos presentó un error de tipo:
Package deployment failed with: INSTALL_FAILED_VERSION_DOWNGRADE
Una solución interesante se presenta en este blog, pero se debe tener en cuenta las particulariedades de nuestro proyecto. Al parecer existe una copia del mismo software ya instalado en el dispositivo y deseamos instalar una version más antigua y por eso el dispositivo se queja y no permite realizar la instalación.
En el archivo manifiesto del proyecto se hace referencia al nombre del paquete que se va a instalar.
package="com.dsi.ant.antplus.pluginsampler"
Entonces esto no ha cambiado desde el programa que ya  instalamos y nuestro paquete.  Por esto procedemos a cambiar el nombre del paquete y asi será un nuevo software y se podrá instalar.

Finalmente se logra instalar el programa compilado y con posibilidades para ser modificado para nuestros fines.

jueves, 30 de abril de 2015

ANT+ smartphone dev

El protocolo ANT+ es utilizado por varios fabricantes para integrar la recolección de datos de diferentes dispositivos.  Por ejemplo, se podría tener un reloj que utilice este protocolo para obtener los valores de un GPS, banda de frecuencia cardiaca, sensor de velocidad , cadencia de pedaleo, báculas, etc.
Lo interesante es que los teléfonos estan incluyendo soporte para éste tipo de protocolos, dos ejemplos son Samsung (Galaxy S4) y varios modelos de Sony.
En teoría existen muchas aplicaciones que utilizarían muchos de los sensores para diferentes fines.
Queremos desarrollar aplicaciones con android que utilicen datos recolectados mediante el protocolo ANT+.
Un blog que sirve de referencia es
http://community.giffgaff.com/t5/Blog/ANT-Connect-Your-Smartphone-with-Sport-amp-Fitness-Accessories/ba-p/14835939

La aplicación de prueba que utilizaremos se llama "ANT+ Plugin Sampler" y podemos encontrar info sobre el desarrollo en
http://www.thisisant.com/developer/ant/ant-in-android/