Hoy en día podemos rastrear la posición GPS con varios dispositivos como teléfonos inteligentes, dispositivos portátiles y dispositivos de mano, pero ¿cómo podemos almacenar posiciones GPS masivas de una manera efectiva para el posterior procesamiento, análisis y comparación con la información de otro dispositivo? Hemos creado un procedimiento completo para habilitar un módulo GPS como dispositivo serial en una Raspberry Pi, luego leer la información del GPS y enviarla a una base de datos Postgresql. El tutorial tiene varios pasos desde la instalación del software, scripts para monitorear los datos almacenados.
Video
Conexión modulo GPS
Este es el arreglo de pines para el UBlox Neo 6M:
VCC 3.3V (Pin 1)
RX TXD/GPIO 14 (Pin 8)
TX RXD/GPIO 15 (Pin 10)
GND Ground (Pin 6)
A continuación mostramos los pines de la Raspberry:
Pasos
En una session en la Raspberry:
Conectar al wifi
Activar (Enable) ssh on Preferences/Rasbberry Pi Configuration/Interfaces/SSH
Revisar el IP interno en el Terminal:
ifconfig
Conectar a través de Putty (en Windows):
Host Name: pi@192.168.1.XX Port:22
Establecer (Enable) UART:
En prompt: sudo raspi-config
En 5. Interfacing Options / P6 Serial:
Would you like a login ... ? = No
Would you like the serial ... ? = Yes
Finish and Reboot
Verificar que el gps mande información al serial:
cat /dev/serial0
Instalar postgres:
sudo apt-get update
sudo apt install postgresql
Ver si la base de datos esta funcionando:
sudo service postgresql status
Crear usuario y tabla por defecto:
sudo -u postgres createuser --superuser pi
Crear usuario:
postgres@raspberrypi:~$ createuser --interactive -P
Enter name of role to add: hatari
Enter password for new role: labs
Enter it again: labs
Shall the new role be a superuser? (y/n) y
Crear base de datos:
createdb -O hatari gpsposition
Revisar bases de datos y crear tabla:
psql gpsposition -U hatari -h localhost
\l
\c gpsposition
CREATE TABLE datecoords (
id serial primary key,
easting numeric,
northing numeric,
elevation numeric,
date timestamp
);
\d datecoords
Instalar sqlalchemy, psycopg2 and pynmea:
pip3 install sqlalchemy
pip3 install psycopg2
pip3 install pynmea2
Crear un folder para los códigos:
mkdir gpsScripts
cd gpsScripts
Crear un código para leer y almacenar los datos GPS:
nano gpsPosition.py
Correr el código (por 30 segundos):
python3 gpsPosition.py
Crtl+Z
Revisar si los registros están en la base de datos:
psql gpsposition -U hatari -h localhost
SELECT * FROM datecoords;
\q
Correr el código en el "background”:
chmod +x gpsPosition.py
nohup /home/pi/gpsScripts/gpsPosition.py > output.log &
Revisar si el código esta corriendo:
ps ax | grep gpsPosition.py
También puede revisar la base de datos:
date
psql gpsposition -U hatari -h localhost
select * from datecoords order by date desc limit 10;
Código
Este es el código en Python que lee la información serial, interpreta la sentencia NMEA y la almacena en la base de datos:
#!/usr/bin/env python3 import io, time, os, serial import pynmea2 from datetime import datetime,date, timedelta from sqlalchemy import create_engine from sqlalchemy import Column, Integer, Float, Date from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker db_string = "postgres://hatari:labs@localhost:5432/gpsposition" db = create_engine(db_string) base = declarative_base() Session = sessionmaker(db) session = Session() class Coords(base): __tablename__ = 'datecoords' id = Column(Integer, primary_key=True) easting = Column(Float) northing = Column(Float) elevation = Column(Float) date = Column(Date) ser = serial.Serial('/dev/serial0', 9600, timeout=5.0) sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser)) while True: try: line = sio.readline() if line[:6]=="$GPGGA": msg = pynmea2.parse(line) print(msg.latitude,msg.longitude,msg.altitude) gpsTime = datetime.combine(date.today(), msg.timestamp) gpsRead = Coords(easting=msg.latitude, northing=msg.longitude, elevation=msg.altitude,date= gpsTime + timedelta(hours=1)) session.add(gpsRead) session.commit() except serial.SerialException as e: print('Device error: {}'.format(e)) break except pynmea2.ParseError as e: print('Parse error: {}'.format(e)) continue