Como crear un heatmap de las redes wifi a partir de datos obtenidos con tu celular Android
10 de Diciembre de 2013
Hace mucho tiempo que quería jugar con mi celular Android, escribiendo unos scripts Python para obtener datos y luego visualizarlos en un mapa. Así que hace unos meses (y escribo el post solamente hoy...) desarrollé un pequeño script que por una cierta ubicación (con el GPS del celular prendido) escanea las redes wifi emitiendo cerca. La idea es de poder hacer luego un heatmap de las redes wifi de una zona.
Lo necesario
Bueno, necesitamos un celular con el sistema operativo Android . Yo tengo un Nexus S con la versión 4.1.2 pero debería funcionar con una gran variedad de modelos y de versiones. Lo importante es que el cel tenga un GPS. También debemos instalar:
- SL4A (Scripting Layer for Android)
- Python for Android
Hace mucho tiempo que los instalé asi que no me acuerdo muy bien pero creo que el segundo se instala a partir del primero (Para empezar ver este doc). Una vez instalados tenemos 2 apps con los íconos de la imagen siguiente:
El script
El script se usa de la manera siguiente: Con el GPS activado, me pongo en un lugar y lo ejecuto. Una vez ejecutado me desplazo y repito el mismo proceso hasta cubrir de manera regular mi zona (en mi caso el distrito de Barranco en Lima). Para cada ejecución el script escribe en un archivo texto las coordenadas de mi ubicación (lat, long), su precisión, el número de redes wifi identificadas y el modo de ubicación (GPS o por triangulación de antenas wifi). A continuación el script comentado para que sea entendible:
Aca solamente busqué los datos que me interesan pero el módulo android permite obviamente recuperar mucho más información. Por ejemplo por las redes wifi se puede obtener sus nombres, sus modos de seguridad, etc...
Muy bien, ya que tenemos el script listo lo podemos cargar al celular y luego ejecutarlo. Entonces conectamos nuestro Android por USB a una compu y copiamos el script en /sl4a/scripts
Ahora podemos desconectar el cel de la compu, activar el GPS (entonces mejor estar afuera) y abrir la app SL4A. Vemos una lista de scripts (los pre instalados con los cuales podemos jugar al inicio para ver las posibilidades) y el nuestro: heatmap_wifi.py. Hacemos clic en este. Debemos obtener lo mismo que en la imagen a continuación:
Los diferentes íconos significan (de izquierda hacia derecha):
- Ejecutar el script (lo que hice)
- Ejecutar como tarea de fondo
- Editar el script
- Guardar
- Borrar
Entonces hacemos clic en el ícono de izquierda, lo que hace aparecer una consola. Después de unos 45 segundos (porque, como esta indicado en los comentarios del script, esperamos 30 segundos para la señal GPS y 15 para escanear las redes wifi, lo cual seguramente es demasiado pero quería estar seguro de siempre obtener datos) debemos ver los datos y luego "Terminado!". Si queremos ejecutar de nuevo el script en una otra ubicación, volvemos a hacer lo mismo.
Después de ejecutar el script varias veces podemos ver los datos.
Los datos
Para ver los datos, conectamos de nuevo el cel a la compu con el cable USB y vamos en la carpeta /storage/sdcard0/logs/ (No es el mejor lugar para poner datos pero tenía un error si los ponian en otra carpeta). Los datos se encuentran en el arhivo lista_wifis.txt. Lo copiamos en nuestra compu.
Después de agregar manualmente los nombres de columnas, el archivo lista_wifis.txt es asi (solo pongo las primeras líneas):
A partir de este archivo podemos muy facilmente obtener un shapefile con QGIS utilizando la excelente herramienta "Añadir capa de texto delimitado". Pero eso ya sabemos hacerlo, hoy día vamos a ver un otro formato y una manera original y super sencilla de publicar nuestros datos.
Este formato es el GeoJSON. Es un formato bastante nuevo y que tiene mucha popularidad en la web. Tiene un hermano menor, el TopoJSON que soporta la topología y por eso el archivo obtenido es más ligero. Pero en nuestro caso, como tenemos puntos, no hay diferencia asi que usaremos el formato GeoJSON.
No cambiamos nuestras buenas costumbres y usamos QGIS para obtener este archivo GeoJSON. A partir del archivo shape obtenido con la herramienta "Añadir capa de texto delimitado", al cual hemos guardado solamente el campo "num_wifis" (con el excelente plugin Table Manager) hacemos clic derecho en el nombre de la capa y luego "Guardar como". Escojamos "GeoJSON" como formato y le damos el nombre wifis_barranco.geojson. Nada más! Como es un formato texto lo pueden abrir con su editor de texto (para ver el "código") o mejor en QGIS. Pero hay aún mejor! Como lo dije, el GeoJSON es muy utilizado en la web así que sería interesante visualizar nuestros datos en una página web con, por ejemplo, un fondo OSM. Vamos a ver 2 maneras de hacerlo.
Visualización
La primera, la manera de los flojos es la más fácil y el resultado es muy bueno. Vamos a aprovechar de las posibilidades que nos da GitHub para visualizar datos geográficos. En efecto desde algunos meses GitHub permite ver directamente los datos en formatos GeoJSON, TopoJSON o JSON en un mapa y no como texto. Solo se necesita una cuenta GitHub y unos datos geográficos. Lo que hice es crear un nuevo Gist (como hice para el código y los datos) que llamé wifis_barranco.geojson y en el cual copié los datos GeoJSON obtenidos en QGIS.
El resultado es el siguiente (muevan el mapa y hagan clic en los puntos):
Genial no?
Ahora la segunda manera. Vamos a usar la competencia de OpenLayers (que además tarda mucho en sacar su tan esperada versión 3), Leaflet (que también es usado por GitHub en el ejemplo anterior). Descargamos la última versión (0.7.1) y hacemos un pequeño cambio en nuestro archivo wifis_barranco.geojson. En la primera línea agregramos (para poder llamar los datos como variable):
var wifis = |
Pongo el código completo de la página HTML en otro Gist acá. El resultado es el siguiente:
Esa vez hemos escrito un poco mas de código pero no fue tan difícil (Leaflet tiene varios ejemplos que permiten empezar rapidamente). Además de no usar el mismo fondo que GitHub, hemos también customizado el contenido de los Pop-up con el texto "Número de wifis detectados:". Para los puntos utilizamos los íconos que vienen por defecto pero obviamente se puede usar otros.
Bueno casi hemos terminado. Al inicio de este post, hablé de un heatmap de la densidad de las redes wifi, así que vamos por eso!
Heatmap
Después de buscar las opciones disponibles en internet encontré el proyecto HeatCancas. No creo que sea lo más fácil de usar pero hay una demo y pude encontrar en la web códigos que me ayudaron, así que al final no me tomó mucho tiempo.
Lo que necesitamos es descargar el código del proyecto y modificar el archivo wifis_barranco.geojson para obtener wifis_barranco.js. Pongo también el código de la página HTML acá.
Y finalmente obtenemos este mapa (pueden activar/desactivar las 2 capas con el botón de arriba a la derecha):
Hecho! Tenemos nuestro heatmap. El color claro indica valores altos y el oscuro valores bajos. Usamos HeatCanvas porque nos permitió tener un resultado ligero y de manera rápida. Pero hubieramos podido crear un raster con QGIS o con R y luego mostrarlo en Leafleat. Seguramente hubieramos obtenido un resultado mas coherente porque en este caso, la interpolación parece ser más influenciada por la cantidad de puntos que por sus pesos (la cantidad de wifis). Pero bueno tenemos un resultado interesante y vimos todos los pasos que constituyen un proyecto: tener la idea (que no es tan obvio ), desarrollar el script, obtener/crear los datos y luego visualizarlos de manera básica y de manera avanzada.