Jugando con el GPS del celular (Android) con Python

La mayoría de los celulares actuales integran GPS, siendo este poco utilizado/aprovechado para los usuarios que desconocen todas las ventajas que podría tener el utilizar esta característica de sus celulares.

Primero que nada...

¿Cómo leer los datos del GPS?

Existe algo llamado NMEA:

“NMEA 0183 (o NMEA de forma abreviada) es una especificación combinada eléctrica y de datos entre aparatos electrónicos marinos y, también, más generalmente, receptores GPS.” Wikipedia

Me vino a la mente que “nmea” es por el león de Heracles, pero no lo puedo confirmar :P

En otras palabras, se pueden leer todos los datos del GPS en formato CVS (valor separado por coma), vamos a ver algunas cosas rápidas del estándar NMEA:

Satélites utilizados:
 $GPGSA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>,<13>,<14>,<15>,<16>,<17><Checksum><CR><LF>

Siendo el 1 es la forma en la que está trabajando el GPS del celular:

Posibles valores:
M: Manual (Forzar a trabajar en 3D/2D)

A: Automático

El 2 es el modo 2:
1=No fijo, 2=2D, 3=3D

 

Del 3 al 14 ID's de satélites usados (valor numérico).
15 Position dilution of precision (PDOP)

16 Horizontal dilution of precision (HDOP)

17 Vertical dilution of precision (VDOP)

En fin, no tiene caso hacer una copia de los RFC que existen sobre este protocolo, por lo que vamos directamente al grano:

Para poder acceder a los datos del GPS en la PC (me parece más bonito y útil usar el GPS en la PC que en el celular) vamos a utilizar una herramienta llamada ShareGPS (que pueden encontrar en el Play Store) y adb (que viene en el SDK de android) o “adb lite” (google).

Iniciamos ShareGPS en el celular y en la configuración marcamos: “Use USB”

Ahora en adb vamos a redireccionar el puerto (sí, se puede redireccionar puertos del celular a la pc):
 Zer0-null:/home/xianur0 # adb forward tcp:50000 tcp:50000

Con esto el puerto 50000 del celular queda en el 50000 de nuestra máquina, probemos:
Zer0-null:/home/xianur0 # nc -vvv localhost 50000

nc: connect to localhost port 50000 (tcp) failed: Connection refused

Connection to localhost 50000 port [tcp/mrt] succeeded!

$GPGSV,4,1,16,01,,,,03,45,070,,04,,,,05,,,*4E

$GPGSV,4,2,16,06,27,054,,07,35,320,,08,13,293,,10,18,291,*7A

$GPGSV,4,3,16,11,11,151,,13,73,350,,16,20,036,,19,46,108,*7F

$GPGSV,4,4,16,20,13,185,,23,69,132,,28,12,233,,30,,,*44

[…]

Esos datos raros que pueden ser ahí es directamente los datos NMEA, ahora la cosa es bastante fácil, podemos conectarnos con python al puerto 50000 de localhost (también se podría a través de una red wifi, pero me gusta más esta forma).
 import socket,string

# -*- coding: utf-8 -*-

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect(('localhost', 50000))

 

while 1:

linea = s.recv(250)

print linea

 

Con esto haremos exactamente lo mismo que netcat, pero vamos un por más allá, recuerdan que dije que está en formato CVS todo?
            datos=string.split(linea,',')

 

Con esto ya tenemos cada valor de la linea en datos, ahora podemos analizarlo:
            try:

result = {

'$GPRMC': GPRMC ,

'$GPGSV': GPGSV

}[datos[0]](datos[1:])

except KeyError:

pass

 

Para los que no estén familiarizados con python, este no tiene swich como tal, entonces esta es mi versión de este.

Lo que hacemos con esto es llamar a cada una de esas funciones (GPRMC,GPGSV,GPGSA) cada vez que una linea tenga por ejemplo “$GPRMC” que llamaría a la función GPRMC , pasandole como argumento todos los elementos de datos excepto el primero (no tiene caso mandarle “$GPRMC ” por ejemplo xD)

Vamos a parsear el primero (GPRMC nos indica el estado de la conexión los satélites y los datos obtenidos de este):
def GPRMC (datos):

if datos[1] != 'V':

print "[-] Conectado con satelites!"

print "[-] Hora actual: "+datos[0][0:2]+":"+datos[0][2:4]+":"+datos[0][4:6]+" con "+datos[0][7:]+" milisegundos"

print "[-] Coordenadas actuales: ("+datos[2]+","+datos[4]+")"

print "[-] Latitud Hemisferio: "+datos[3]

print "[-] Longitud Hemisferio: "+datos[5]

print "[-] Velocidad actual: "+datos[6]+" nudos"

azimut=int(datos[7])

rumbo=''

if(azimut==0):

rumbo='Norte'

elif(azimut<90 and azimut > 0):

rumbo='Noreste'

elif(azimut==90):

rumbo='Este'

if(azimut>90 and azimut < 180):

rumbo='Sureste'

if(azimut==180):

rumbo='Sur'

if(azimut>180 and azimut<360):

rumbo='Suroeste'

if(azumit==360):

rumbo='Oeste'

print "[-] Rumbo: "+rumbo+" ("+datos[7]+" grados)"

print "[-] Fecha UTC: "+datos[8]

 

Azimut es una forma de medir la dirección hacia la cual vamos (rumbo) en grados:

0° sería el norte, 90 el Este, 180 el Sur y 360 el Oeste.

Nota de interés: La fecha UTC la genera el receptor GPS en base a la de los satélites que está utilizando.

Ahora va  GPGSV que nos da información sobre los satélites visibles
def GPGSV (datos):

print datos

print "\n[!] Información de satélites visibles: "

print "[-] Total Número de mensajes: "+datos[0]

print "[-] Número de mensaje: "+datos[1]

print "[-] Satélites visibles: "+datos[2]

c=0

for a in range(3):

print "[-] Satélite número: "+datos[3+c]

print "\t[-] Grados de elevación: "+datos[3+c+1]

print "\t[-] Asimut: "+datos[3+c+2]

print "\t[-] SNR: "+datos[3+c+3]+" dB-Hz"

c=c+4

 

Nota de interés:  SNR es la relación señal/ruido y en base a esta se puede calcular la calidad de enlace con el satélite.

Código completo.


 

import socket,string

# -*- coding: utf-8 -*-

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect(('localhost', 50000))

 

def GPRMC (datos):

if datos[1] != 'V':

print "[!] Conectado con satelites!"

print "[-] Hora actual: "+datos[0][0:2]+":"+datos[0][2:4]+":"+datos[0][4:6]+" con "+datos[0][7:]+" milisegundos"

print "[-] Coordenadas actuales: ("+datos[2]+","+datos[4]+")"

print "[-] Latitud Hemisferio: "+datos[3]

print "[-] Longitud Hemisferio: "+datos[5]

print "[-] Velocidad actual: "+datos[6]+" nudos"

azimut=int(datos[7])

rumbo=''

if(azimut==0):

rumbo='Norte'

elif(azimut<90 and azimut > 0):

rumbo='Noreste'

elif(azimut==90):

rumbo='Este'

if(azimut>90 and azimut < 180):

rumbo='Sureste'

if(azimut==180):

rumbo='Sur'

if(azimut>180 and azimut<360):

rumbo='Suroeste'

if(azimut==360):

rumbo='Oeste'

print "[-] Rumbo: "+rumbo+" ("+datos[7]+" grados)"

print "[-] Fecha UTC: "+datos[8]

 

def GPGSV (datos):

print datos

print "\n[!] Información de satélites visibles: "

print "[-] Total Número de mensajes: "+datos[0]

print "[-] Número de mensaje: "+datos[1]

print "[-] Satélites visibles: "+datos[2]

c=0

for a in range(3):

print "[-] Satélite número: "+datos[3+c]

print "\t[-] Grados de elevación: "+datos[3+c+1]

print "\t[-] Asimut: "+datos[3+c+2]

print "\t[-] SNR: "+datos[3+c+3]+" dB-Hz"

c=c+4

 

 

while 1:

linea = s.recv(250)

if linea == '':

raise RuntimeError("socket connection broken")

datos=string.split(linea,',')

try:

result = {

'$GPRMC': GPRMC,

'$GPGSV': GPGSV

}[datos[0]](datos[1:])

except KeyError:

pass

By Xianur0

Penulis : Megabyte ~ Sebuah blog yang menyediakan berbagai macam informasi

Artikel Jugando con el GPS del celular (Android) con Python ini dipublish oleh Megabyte pada hari viernes, 1 de febrero de 2013. Semoga artikel ini dapat bermanfaat.Terimakasih atas kunjungan Anda silahkan tinggalkan komentar.sudah ada 1comentarios: di postingan Jugando con el GPS del celular (Android) con Python
 

1 comentarios:

  1. amigo sera que tendrás el capture del código en python ya que en donde muestras el código completo todo esta al mismo nivel y no se sabe que sentencia depende de la otra, si pusieras el capture seria de mucha ayuda.

    ResponderEliminar