Skip to content

johnivansn/GPS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📡 Protocolo GPS - Sistema de Rastreo en Tiempo Real


🎯 Objetivo del Proyecto

Diseñar e implementar un protocolo de comunicación eficiente para dispositivos GPS que permita transmitir datos de localización y estado en tiempo real a un servidor central, considerando:

  • Restricciones de batería en dispositivos móviles
  • Ancho de banda limitado (redes 2G/3G/4G)
  • Transmisión confiable sobre redes no confiables
  • Seguridad básica de los datos

📚 Fundamentos Teóricos

Conceptos Aplicados

Capa Conceptos Implementados Ubicación en el Código
Capa de Enlace CRC-16, detección de errores calcular_checksum()
Capa de Red Direccionamiento IP, enrutamiento Sockets UDP
Capa de Transporte UDP, ARQ, control de flujo ACK, reintentos, timeouts
Capa de Aplicaciones Cliente-servidor, sockets Arquitectura completa

🏗️ Arquitectura del Sistema

┌─────────────────┐                    ┌─────────────────┐
│ Dispositivo GPS │                    │ Servidor Central│
│  (Cliente)      │                    │   (Receptor)    │
├─────────────────┤                    ├─────────────────┤
│ • Genera datos  │ ───UDP (30B)────>  │ • Recibe datos  │
│ • Empaqueta     │                    │ • Valida CRC    │
│ • Envía cada 5s │ <───ACK (10B)───   │ • Almacena log  │
│ • Espera ACK    │                    │ • Registra stats│
└─────────────────┘                    └─────────────────┘

🔬 Diseño del Protocolo

1️⃣ Formato del Mensaje (30 bytes)

┌──────────────────────────────────────────────────────────┐
│                    CABECERA (10 bytes)                   │
├────┬────┬──────┬──────┬──────────┬────────┬──────────────┤
│VER │TIPO│ ID   │ SEQ  │CHECKSUM  │ FLAGS  │   (reserva)  │
│ 1B │ 1B │ 2B   │ 2B   │  2B      │ 2B     │              │
└────┴────┴──────┴──────┴──────────┴────────┴──────────────┘

┌──────────────────────────────────────────────────────────┐
│                     PAYLOAD (20 bytes)                   │
├────────┬─────────┬─────┬──────────┬─────┬───────┬───┬────┤
│LATITUD │LONGITUD │ ALT │TIMESTAMP │ VEL │RUMBO  │BAT│EST │
│  4B    │   4B    │ 2B  │   4B     │ 2B  │  2B   │1B │ 1B │
└────────┴─────────┴─────┴──────────┴─────┴───────┴───┴────┘

Campos Detallados

Campo Tamaño Descripción Ejemplo
VER 1 byte Versión del protocolo 0x01
TIPO 1 byte Tipo de mensaje (GPS/ACK/HEARTBEAT) 0x01 = GPS
ID_DISP 2 bytes Identificador único del dispositivo 1234
SEQ 2 bytes Número de secuencia (0-65535) 42
CHECKSUM 2 bytes CRC-16 para detección de errores 0x3FF5
FLAGS 2 bytes Estado del dispositivo (ver tabla abajo) 0x0C
LATITUD 4 bytes Grados × 10⁷ (permite ±180°) -173935000 = -17.3935°
LONGITUD 4 bytes Grados × 10⁷ (permite ±180°) -661570000 = -66.1570°
ALTITUD 2 bytes Metros sobre el nivel del mar 2558 m
TIMESTAMP 4 bytes Unix timestamp (segundos desde 1970) 1738267815
VELOCIDAD 2 bytes km/h × 10 450 = 45.0 km/h
RUMBO 2 bytes Grados × 10 (0-3600) 1350 = 135.0°
BATERÍA 1 byte Porcentaje (0-100) 85 %
ESTADO 1 byte Byte adicional de estado 0x00

Flags de Estado

Bit Nombre Descripción
0x01 BATERÍA_BAJA Batería < 20%
0x02 SOS Señal de emergencia
0x04 EN_MOVIMIENTO Velocidad > 5 km/h
0x08 IGNICIÓN_ON Motor encendido

2️⃣ Eficiencia del Protocolo

Comparación de Tamaño

# Nuestro protocolo binario
mensaje_binario = 30 bytes

# Alternativa JSON (mismo contenido)
mensaje_json = {
    "id": 1234,
    "seq": 42,
    "lat": -17.3935,
    "lon": -66.1570,
    "alt": 2558,
    "vel": 45.0,
    # ...
}
# Tamaño: ~180 bytes

# AHORRO: 83% de ancho de banda

Impacto en Batería

Envío cada 5 segundos:
• Mensajes/día: 17,280
• Datos/día: 30 bytes × 17,280 = ~500 KB
• Consumo red 3G: ~0.2% batería/día

Si usáramos JSON:
• Datos/día: 180 bytes × 17,280 = ~3 MB
• Consumo red 3G: ~1.2% batería/día

3️⃣ Método de Transmisión: UDP

¿Por qué UDP y no TCP?

Característica UDP TCP Decisión
Overhead 8 bytes 20+ bytes ✅ UDP
Handshake No requiere 3-way handshake ✅ UDP (ahorra batería)
Latencia Baja Media/Alta ✅ UDP (tiempo real)
Confiabilidad No garantizada Garantizada ⚠️ TCP mejor...
Orden No garantizado Garantizado ⚠️ TCP mejor...

Decisión: Usar UDP + mecanismos propios de confiabilidad

Fundamento Teórico

"UDP no asegura la integridad de los datos ni implementa control de flujo... Es extremadamente simple, no necesita almacenar información acerca del intercambio en curso"

"El streaming es tolerante a pérdidas pero requiere retardos acotados"

Aplicación: GPS tolera perder 1-2 posiciones, pero necesita latencia baja.


4️⃣ Manejo de Errores (Multicapa)

Capa 1: CRC-16 (Detección)

def calcular_checksum(datos):
    """
    Implementación de CRC-16-ANSI
    Polinomio: 0xA001
    """
    crc = 0xFFFF
    for byte in datos:
        crc ^= byte
        for _ in range(8):
            if crc & 0x0001:
                crc = (crc >> 1) ^ 0xA001
            else:
                crc >>= 1
    return crc & 0xFFFF

Capacidad de Detección:

  • ✅ 100% de errores de 1 bit
  • ✅ 100% de errores de 2 bits
  • ✅ 99.998% de errores de burst ≤ 16 bits

Fundamento Teórico:

"CRC detecta errores en burst de una longitud menor o igual al grado del polinomio generador"


Capa 2: Numeración de Secuencia

# En el servidor
if seq <= ultima_seq:
    # Mensaje duplicado
    self.mensajes_duplicados += 1
    
if seq > ultima_seq + 1:
    # Mensajes perdidos
    perdidos = seq - ultima_seq - 1
    self.mensajes_perdidos += perdidos

Detecta:

  • 🔄 Mensajes duplicados
  • 📉 Mensajes perdidos
  • ⚠️ Desorden en la recepción

Fundamento Teórico:

"Con sólo dos números de paquete es suficiente... El receptor debe verificar que los paquetes recibidos tengan el número de secuencia esperado"


Capa 3: ACK (Confirmación)

# Cliente envía datos
mensaje = empaquetar_mensaje_gps(...)
socket.sendto(mensaje, servidor)

# Espera ACK con timeout
socket.settimeout(3.0)
try:
    ack, _ = socket.recvfrom(1024)
    # ACK recibido ✓
except socket.timeout:
    # Timeout, reintentar

Fundamento Teórico:

"Al recibir un ACK debe marcar ese paquete como recibido"


Capa 4: Reintentos con Backoff

MAX_REINTENTOS = 3
TIMEOUT_BASE = 3.0

for intento in range(MAX_REINTENTOS):
    timeout = TIMEOUT_BASE * (2 ** intento)  # Backoff exponencial
    socket.settimeout(timeout)
    
    try:
        enviar_mensaje()
        ack = esperar_ack()
        break  # Éxito
    except socket.timeout:
        if intento == MAX_REINTENTOS - 1:
            print("❌ Mensaje perdido definitivamente")

Fundamento Teórico:

"La fase de espera exponencial... ajusta las retransmisiones de manera que estimen la carga actual"


5️⃣ Seguridad Básica

Mecanismos Implementados

# 1. Autenticación por ID de Dispositivo
dispositivos_autorizados = {1234, 5678, 9012}

if id_dispositivo not in dispositivos_autorizados:
    print("⛔ Dispositivo no autorizado")
    return

# 2. Validación de Timestamp
timestamp_actual = time.time()
diferencia = abs(timestamp_mensaje - timestamp_actual)

if diferencia > 300:  # 5 minutos de tolerancia
    print("⚠️ Timestamp sospechoso (posible replay attack)")

# 3. Verificación de Checksum
if not verificar_checksum(mensaje):
    print("❌ Mensaje corrupto o manipulado")
    return

💻 Estructura del Código

GPS/
│
├── src/
│   ├── gps_protocolo.py  # Librería compartida
│   ├── gps_cliente.py    # Simulador de dispositivo GPS
│   └── gps_servidor.py   # Servidor central
└── README.md

🚀 Guía de Uso

Requisitos

  • Python 3.9+ (recomendado)

Quick Start

# 1) Probar el protocolo
python gps_protocolo.py

# 2) Iniciar servidor
python src/gps_servidor.py

# 3) Ejecutar cliente
python src/gps_cliente.py

Paso 1: Probar el Protocolo

# Ejecutar tests automáticos
python src/gps_protocolo.py

Salida esperada:

=== Prueba del Protocolo GPS ===

1. Creando mensaje GPS...
   Tamaño del mensaje: 30 bytes
   ✓ Mensaje válido

2. Desempaquetando mensaje...
   ✓ Checksum correcto
   ✓ Datos íntegros

3. Probando mensaje corrupto...
   ✓ Error detectado: Checksum inválido

4. Creando mensaje ACK...
   ✓ ACK válido (10 bytes)

Paso 2: Iniciar el Servidor

# Opción 1: Configuración por defecto
python src/gps_servidor.py

# Opción 2: Puerto personalizado + ACK deshabilitado
python src/gps_servidor.py 8888 false

# Opción 3: Puerto + ACK + log path + max log (KB) + ventana (seg)
python src/gps_servidor.py 8888 true logs/gps_log.txt 1024 300

# Opción 4: Deshabilitar auto-cliente
python src/gps_servidor.py 9999 true gps_log.txt 1000 300 false

Interfaz Python (PyQt5)

La interfaz ahora es nativa en Python y controla el servidor/cliente directamente.

# Instalar UI
pip install PyQt5

# Iniciar servidor (puerto por defecto 9999)
python src/gps_servidor.py

# Iniciar servidor en otro puerto (ej: 8888)
python src/gps_servidor.py 8888

# Abrir UI
python src/gps_ui.py

Solución de problemas (puerto en uso)

Si el puerto 9999 está ocupado:

netstat -ano | findstr :9999
taskkill /PID <PID> /F

Pantalla del servidor:

============================================================
  SERVIDOR GPS CENTRAL
============================================================
  Puerto: 9999
  ACK automático: Sí
============================================================

[✓] Servidor escuchando en puerto 9999
[✓] Esperando dispositivos GPS...

Paso 3: Ejecutar el Cliente

# Modo interactivo (recomendado)
python gps_cliente.py

Menú interactivo:

┌────────────────────────────────────────────┐
│     SIMULADOR DE DISPOSITIVO GPS           │
└────────────────────────────────────────────┘

Seleccione el modo de operación:

  1. 🅿️  Vehículo estacionado
  2. 🏙️  Movimiento urbano (30 km/h)
  3. 🛣️  Carretera (80 km/h)
  4. ⚙️  Configuración personalizada
  5. 💓 Enviar solo HEARTBEAT
  6. ❌ Salir

Opción: _

⚠️ Solución de Problemas

Error: "Address already in use" / "Puerto en uso"

Causa: El puerto 9999 ya está siendo usado por otro programa.

Soluciones:

  1. Esperar 30-60 segundos y reintentar
  2. Usar otro puerto:
   python src/gps_servidor.py 8888
   python src/gps_cliente.py 127.0.0.1 8888 1234
  1. Liberar el puerto (Windows):
   netstat -ano | findstr :9999
   taskkill /PID <número> /F

Paso 4: Observar el Intercambio

En el cliente:

[→] Mensaje #1 enviado (30 bytes)
    Pos: -17.393500°, -66.157000°
    Vel: 0.0 km/h, Bat: 100%
[←] ACK recibido para mensaje #1

[→] Mensaje #2 enviado (30 bytes)
    Pos: -17.393520°, -66.156980°
    Vel: 32.5 km/h, Bat: 99%
[←] ACK recibido para mensaje #2

En el servidor:

────────────────────────────────────────────────────────────
[←] DATOS GPS RECIBIDOS
────────────────────────────────────────────────────────────
  Origen:       127.0.0.1:54321
  Dispositivo:  GPS #1234
  Secuencia:    #2
  Coordenadas:  -17.3935200°, -66.1569800°
  Velocidad:    32.5 km/h
  Rumbo:        45.0°
  Batería:      99%
  Estado:       EN MOVIMIENTO, 🔑IGNICIÓN ON
────────────────────────────────────────────────────────────

[→] ACK enviado a GPS #1234 (SEQ=2)

📊 Captura con Wireshark

Configuración

  1. Abrir Wireshark
  2. Seleccionar interfaz: Loopback (lo0)
  3. Filtro de captura: udp.port == 9999
  4. Iniciar captura
  5. Ejecutar cliente y servidor

Análisis de Paquete GPS (30 bytes)

Frame 1: 58 bytes on wire
Ethernet II
Internet Protocol Version 4
    Src: 127.0.0.1
    Dst: 127.0.0.1
User Datagram Protocol
    Src Port: 54321
    Dst Port: 9999
    Length: 38 (8 UDP + 30 datos)
Data (30 bytes):
    01 01 04 d2 00 01 3f f5 00 0c f5 15 7e 50 fc 0e
    74 7a 09 fe 67 fd b3 08 01 c2 05 46 55 00

Desglose hexadecimal:

Bytes Campo Valor Hex Valor Decimal Significado
01 VER 0x01 1 Versión 1
01 TIPO 0x01 1 DATOS_GPS
04 d2 ID_DISP 0x04D2 1234 GPS #1234
00 01 SEQ 0x0001 1 Mensaje #1
3f f5 CHECKSUM 0x3FF5 16373 CRC-16
00 0c FLAGS 0x000C 12 MOV + IGN
f5 15 7e 50 LAT -173935000 -17.3935° Latitud
fc 0e 74 7a LON -661570000 -66.1570° Longitud
09 fe ALT 0x09FE 2558 2558 m
67 fd b3 08 TIME 0x67FDB308 1744511752 2025-04-10
01 c2 VEL 0x01C2 450 45.0 km/h
05 46 RUMBO 0x0546 1350 135.0°
55 BAT 0x55 85 85%
00 EST 0x00 0 Normal

Análisis de ACK (10 bytes)

Data (10 bytes):
    01 02 04 d2 00 01 a7 3c 00 00
Bytes Campo Significado
01 VER Versión 1
02 TIPO ACK
04 d2 ID_DISP GPS #1234
00 01 SEQ_ACK Confirmando mensaje #1
a7 3c CHECKSUM CRC-16 del ACK
00 00 FLAGS Sin flags

📈 Resultados y Estadísticas

Estadísticas del Servidor (después de 100 mensajes)

============================================================
  ESTADÍSTICAS DEL SERVIDOR
============================================================
  Mensajes recibidos:  100
  Mensajes perdidos:   2 (2%)
  Mensajes duplicados: 0
  Errores detectados:  1 (checksum inválido)
  Dispositivos activos: 1
============================================================

  DISPOSITIVOS CONECTADOS:
  ----------------------------------------------------------
  GPS #1234 | Mensajes: 100 | Última SEQ: 102 | Hace: 5s
            | Pos: -17.395123°, -66.152456° |
            | Vel: 45.2 km/h | Bat: 82%
  ----------------------------------------------------------

Análisis de Pérdidas

# Simulación con pérdida de paquetes del 5%
Total enviados:    100 mensajes
Total recibidos:   95 mensajes
Pérdidas:          5 mensajes (5%)
Duplicados:        0 mensajes
Errores CRC:       0 mensajes

# Todos los mensajes perdidos fueron detectados por secuencia
# No hubo datos corruptos no detectados (CRC 100% efectivo)

🎓 Conceptos del Curso Aplicados

1. Capa de Enlace

Concepto: Detección de errores con CRC

def calcular_checksum(datos):
    crc = 0xFFFF
    for byte in datos:
        crc ^= byte
        for _ in range(8):
            if crc & 0x0001:
                crc = (crc >> 1) ^ 0xA001
            else:
                crc >>= 1
    return crc & 0xFFFF

2. Capa de Red

Concepto: Fragmentación y MTU

# Nuestro mensaje (30 bytes) nunca necesita fragmentarse
# MTU típico Ethernet: 1500 bytes
# MTU típico 3G/4G: 1280-1500 bytes
# Nuestro protocolo: 30 bytes << MTU

3. Capa de Transporte

Concepto: UDP + ARQ personalizado

socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Implementamos nuestro propio:
# - Numeración de secuencia
# - ACKs
# - Timeouts
# - Reintentos

4. Capa de Aplicaciones

Concepto: Arquitectura cliente-servidor

# Cliente:
#   - Inicia solicitudes
#   - Gestiona interfaz de usuario
#
# Servidor:
#   - Siempre disponible
#   - Procesa solicitudes
#   - Mantiene estado

🔍 Ventajas del Diseño

✅ Eficiencia

Métrica Valor Comparación
Tamaño mensaje 30 bytes JSON: ~180 bytes (-83%)
Overhead UDP 8 bytes TCP: 20+ bytes (-60%)
Handshake 0 ms TCP: 3-way (50-150ms)
Consumo batería ~0.2%/día JSON: ~1.2%/día (-83%)

✅ Confiabilidad

Mecanismo Efectividad
CRC-16 99.998% detección errores
Secuencia 100% detección duplicados/pérdidas
ACK Confirmación explícita
Reintentos 3 intentos = 99.9% entrega

✅ Escalabilidad

# Soporta hasta:
- 65,535 dispositivos únicos (ID de 2 bytes)
- 65,535 mensajes por sesión (SEQ de 2 bytes)
- Múltiples servidores (arquitectura distribuible)

🎯 Conclusiones

Logros del Proyecto

  1. Protocolo binario eficiente (30 bytes)
  2. Transmisión UDP optimizada para tiempo real
  3. Manejo robusto de errores (4 capas)
  4. Seguridad básica implementada
  5. Aplicaciones funcionales cliente-servidor

Aplicación de Conceptos Teóricos

Concepto Implementación
CRC, checksums calcular_checksum()
IP, MTU, fragmentación Mensaje < MTU
UDP, ARQ, timeouts Sockets + reintentos
Cliente-servidor, sockets Arquitectura completa

Comparación con Protocolos Reales

Protocolo Tamaño Uso Ventaja
Nuestro GPS 30 bytes Rastreo vehicular Eficiencia
NMEA 0183 ~80 bytes GPS náutico/aéreo Texto legible
GPX ~200 bytes Rutas/waypoints Estándar XML
UBX (u-blox) Variable GPS profesional Precisión

📄 Licencia

Este proyecto está bajo la licencia MIT. Ver LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages