Construir un sistema de rastreo de activos con BLE tag no trata de elegir la etiqueta correcta. Trata de la infraestructura que recibe, filtra, transporta y almacena los datos de cientos o miles de etiquetas dispersas en una instalacion. La etiqueta es un transmisor simple; la inteligencia reside en la red de gateways, el procesador edge y el backend en la nube. Este articulo desglosa la arquitectura completa del sistema desde la recepcion de radio hasta el dashboard, con tablas de seleccion de hardware, algoritmos de filtrado, esquemas de pipeline de datos y modelos de costos de despliegue basados en implementaciones en produccion en hospitales, almacenes y plantas de fabricacion.
1. Vision General de la Arquitectura del Sistema
Un sistema de rastreo de activos BLE en produccion tiene cuatro capas, cada una con requisitos distintos de latencia, throughput y confiabilidad:
| Capa |
Componentes |
Latencia |
Volumen |
Impacto de Fallo |
| T1: Capa de Tags |
BLE tags (cientos a miles) |
N/A (solo broadcast) |
~30 bytes/tag/evento |
Activo individual se pierde |
| T2: Capa de Gateway |
Escanners BLE (5-50) |
100-500 ms ciclo |
~50 KB/s pico por GW |
Zona se pierde (10-50 tags) |
| T3: Capa Edge |
Servidor local o appliance |
1-5 s procesamiento |
~200 KB/s agregado |
Retraso de rastreo, sin perdida |
| T4: Capa Cloud |
Backend, DB, dashboard |
1-10 s end-to-end |
~500 KB/s sostenido |
Brecha en datos historicos |
El error de arquitectura mas comun es tratar al gateway como un rele simple que reenvia paquetes BLE crudos a la nube. Con 500 tags a intervalos de 1 segundo y 10 gateways, son 5.000 paquetes por segundo golpeando el endpoint de ingesta, cada uno con lecturas RSSI duplicadas de zonas superpuestas. El filtrado edge no es una optimizacion; es un requisito.
2. Seleccion de Hardware de Gateway
| Plataforma |
Chip BLE |
CPU |
RAM |
Potencia |
Costo BOM |
Ideal para |
| Basada en ESP32 |
ESP32 (dual-mode) |
240 MHz Xtensa x2 |
520 KB SRAM |
2,5W (WiFi+BLE) |
$3-5 |
Sitios pequenos, WiFi |
| Raspberry Pi + USB |
nRF52840 dongle |
1,4 GHz ARM A72 x4 |
1-4 GB |
5-7W |
$45-60 |
I+D, prototipado |
| Gateway dedicado |
nRF52832/52840 + ESP32 |
ESP32 240MHz + nRF52 |
520KB + 256KB |
2-3W |
$15-25 |
Despliegues produccion |
| Gateway industrial (Linux) |
CC2640R2 + WiFi/LTE |
ARM Cortex-A7 1GHz |
512 MB |
5-15W |
$200-400 |
Ambientes duros, celular |
2.1 ESP32 como Gateway: Capacidades y Limites
El ESP32 es la plataforma mas comun para despliegues sensibles al costo porque tiene WiFi y BLE integrados. Sin embargo, el controlador BLE comparte la radio de 2,4 GHz entre WiFi y BLE, lo que significa que no puede escanear BLE mientras transmite WiFi:
| Actividad WiFi |
Brecha de Escaneo BLE |
Perdida (1s) |
Perdida (500ms) |
| Inactivo |
0 ms |
0% |
0% |
| MQTT publish (cada 5s) |
~15 ms/brecha |
0,3% |
0,6% |
| WiFi streaming (continuo) |
~50 ms/brecha |
1,0% |
2,0% |
| OTA update |
~200 ms/brecha |
5-8% |
10-15% |
2.2 Arquitectura de Gateway Dedicado
Los gateways de produccion tipicamente emparejan un nRF52 (escanner BLE dedicado) con un ESP32 (WiFi/CPU). El nRF52 ejecuta escaneo activo continuo y reenvia paquetes via UART/SPI al ESP32, que maneja filtrado, buffer y comunicacion con la nube. Este diseno de chip dual elimina la contencion de radio.
# Lado nRF52: escanner BLE continuo
def ble_scan_callback(adv_report):
packet = {
"mac": adv_report.peer_addr,
"rssi": adv_report.rssi,
"data": adv_report.data,
"ts": get_timestamp_us(),
}
uart_send(json.dumps(packet))
# Lado ESP32: recibir, filtrar, subir en lote
rx_buffer = []
def uart_rx_callback(data):
pkt = json.loads(data)
if should_forward(pkt):
rx_buffer.append(pkt)
if len(rx_buffer) >= BATCH_SIZE or time_since_upload > INTERVAL:
upload_batch(rx_buffer)
rx_buffer.clear()
2.3 Ubicacion de Gateway y Cobertura
| Nivel de Precision |
GW/100m2 |
Espaciado |
Costo/m2 |
Caso de Uso |
| Presencia (sala) |
0,5-1,0 |
10-15 m |
$0,15-0,30 |
Presencia por zona |
| Posicion gruesa (3-5 m) |
2-4 |
5-8 m |
$0,60-1,20 |
Tracking en pasillos |
| Posicion fina (1-2 m) |
6-10 |
3-5 m |
$1,80-3,00 |
Instrumentos quirurgicos |
| Sub-metro (0,5 m) |
15-25 |
2-3 m |
$4,50-7,50 |
Auditoria alto valor |
3. Estrategia de Escaneo BLE
3.1 Escaneo Activo vs. Pasivo
| Parametro |
Escaneo Pasivo |
Escaneo Activo |
| Envia SCAN_REQ |
No |
Si |
| Recibe SCAN_RSP |
No |
Si (hasta 31 bytes extra) |
| Consumo |
Menor (solo Rx) |
Mayor (Tx + Rx) |
| Datos disponibles |
31 bytes |
62 bytes |
3.2 Ventana e Intervalo de Escaneo
| Intervalo |
Ventana |
Duty Cycle |
Captura (1s) |
Captura (500ms) |
| Continuo |
Continuo |
100% |
~99,5% |
~99,0% |
| 1000 ms |
1000 ms |
100% |
~99,5% |
~99,0% |
| 1000 ms |
500 ms |
50% |
~50-65% |
~50-65% |
| 5000 ms |
1000 ms |
20% |
~20-30% |
~20-30% |
3.3 Filtrado de Duplicados a Nivel de Radio
| Modo |
Duplicados |
Paquetes/s (500 tags, 1s, 10GW) |
CPU GW |
| Sin filtrado |
Todos |
~15.000 |
Alto |
| Dedup controlador |
1/tag/ciclo |
~500 |
Bajo |
| Dedup aplicacion |
1/tag/ventana |
~500 |
Bajo-Medio |
4. Filtrado Edge
4.1 Desduplicacion Multi-Gateway
DEDUP_WINDOW_MS = 2000
def deduplicate(raw_reports):
by_tag = group_by_mac(raw_reports)
result = []
for mac, reports in by_tag.items():
if len(reports) == 1:
result.append(reports[0])
continue
best = max(reports, key=lambda r: score_report(r))
result.append(best)
return result
def score_report(r):
rssi_score = (r.rssi + 100) / 70
age_s = (now() - r.ts) / 1000
fresh_score = max(0, 1 - age_s / 5)
gw_reliability = gateway_stats[r.gw_id].uptime_pct
return rssi_score * 0.6 + fresh_score * 0.2 + gw_reliability * 0.2
4.2 Suavizado de RSSI y Rechazo de Outliers
| Filtro |
Ventana |
Latencia |
Reduccion Var. |
Complejidad |
| Crudo (sin filtro) |
1 |
0 s |
0% |
Ninguna |
| Media movil |
5 |
2-5 s |
~55% |
Baja |
| Suavizado exponencial |
Infinito |
1-3 s |
~50% |
Baja |
| Mediana |
3-7 |
1-3 s |
~65% |
Media |
| Kalman |
Adaptativo |
0,5-2 s |
~70% |
Alta |
4.3 Reenvio Basado en Eventos
| Estrategia |
Paq/Tag/Hora |
BW Nube (500 tags) |
Caso de Uso |
| Cada escaneo (1s) |
3.600 |
~14 MB/h |
RTLS sub-segundo |
| Cada 5s (lote) |
720 |
~2,8 MB/h |
Tracking estandar |
| Solo cambio de zona |
~5-20 |
~40 KB/h |
Presencia por sala |
| Umbral + heartbeat |
~2-10 |
~20 KB/h |
Alertas temperatura |
5. Diseno de Pipeline de Datos
5.1 Comparacion de Protocolos de Transporte
| Protocolo |
Overhead |
Confiabilidad |
Latencia |
Potencia GW |
Ideal para |
| HTTP POST (JSON) |
~400 bytes |
TCP garantizado |
100-500 ms |
Alta |
Despliegues pequenos |
| MQTT (QoS 1) |
~20 bytes |
TCP + ACK |
50-200 ms |
Baja |
Despliegues produccion |
| UDP (custom) |
~8 bytes |
Ninguna |
10-50 ms |
Minima |
RTLS tiempo real, LAN |
| LoRaWAN |
~13 bytes |
Confirmado |
1-10 s |
N/A |
Sitios remotos sin WiFi |
5.2 Estructura de Topic MQTT
# Jerarquia de topics MQTT
# Formato: site/zone/gateway/tag/event
site-001/zone-A/gw-01/+/scan
site-001/zone-A/+/tag-005/scan
site-001/+/+/tag-005/zone_change
site-001/+/+/+/battery_low
site-001/+/+/+/temperature_alert
# Payload (JSON, ~80 bytes)
{
"mac": "AA:BB:CC:DD:EE:01",
"rssi": -67,
"gw": "gw-01",
"ts": 1722422400000,
"bat": 85,
"temp": 23.5,
"seq": 4823
}
5.3 Esquema de Datos y Almacenamiento
| Store |
Tecnologia |
Datos |
Retencion |
Query |
| Time-series (hot) |
InfluxDB / TimescaleDB |
Eventos crudos |
7-30 dias |
Rango por tag + tiempo |
| Time-series (cold) |
S3 / Parquet |
Eventos agregados |
1-5 anos |
Batch analytics |
| Relacional |
PostgreSQL / MySQL |
Metadatos, zonas |
Permanente |
CRUD, joins |
| Cache |
Redis |
Ultima posicion |
TTL 5 min |
Sub-ms lookup |
5.4 Calculo de Almacenamiento
# 500 tags, intervalo 5s
tags = 500
events_per_hour = 500 * (3600 / 5) # = 360.000
events_per_day = 360.000 * 24 # = 8.640.000
bytes_per_day = 8.640.000 * 80 # = 691 MB/dia
bytes_per_year = 691 * 365 # = ~252 GB (crudo)
compressed_per_year = 252 / 5 # = ~50 GB (Parquet 5:1)
total_storage_year = 50 * 1.4 # = ~70 GB (con overhead DB)
6. Estimacion de Ubicacion en el Edge
| Algoritmo |
GW Min |
Precision |
CPU Edge |
Calibracion |
Ideal para |
| Proximidad (RSSI max) |
1 |
Sala (5-10m) |
Minimo |
Ninguna |
Presencia simple |
| Centroide ponderado |
3+ |
3-5 m |
Bajo |
Posiciones GW |
Areas abiertas |
| Trilateracion |
3+ |
2-4 m |
Medio |
Exponente path-loss por zona |
Almacenes, pasillos |
| Fingerprinting (kNN) |
4+ |
1-3 m |
Medio-Alto |
Survey RF completo |
Interiores complejos |
| BLE AoA |
1 (antena array) |
0,5-1 m |
Alto |
Calibracion fase antena |
Activos de alto valor |
6.1 Algoritmo de Centroide Ponderado
def estimate_position(reports, gateway_positions):
total_weight = 0
weighted_x = 0
weighted_y = 0
for r in reports:
gw_id = r["gw_id"]
if gw_id not in gateway_positions:
continue
weight = 10 ** (r["rssi"] / 10)
gx, gy = gateway_positions[gw_id]
weighted_x += weight * gx
weighted_y += weight * gy
total_weight += weight
if total_weight == 0:
return None
return (weighted_x / total_weight, weighted_y / total_weight)
7. Confiabilidad del Sistema y Failover
7.1 Monitoreo de Salud de Gateway
| Metrica |
Normal |
Alerta |
Intervalo |
| Paquetes/min |
50-500 |
< 10 o > 2000 |
60 s |
| Temp CPU |
40-65 C |
> 75 C |
300 s |
| WiFi RSSI |
-30 a -65 dBm |
< -75 dBm |
60 s |
| Uptime |
> 99,5% |
< 99% |
Diario |
| Ultimo heartbeat |
< 30 s |
> 120 s |
30 s |
7.2 Buffer ante Perdida de Conexion Edge-Cloud
| Tiempo Max Off |
Buffer (500 tags, 5s) |
Medio |
| 15 min |
~4,3 MB |
RAM |
| 1 hora |
~17 MB |
RAM/SD |
| 4 horas |
~69 MB |
SD/eMMC |
| 24 horas |
~415 MB |
SSD/eMMC |
8. Modelo de Costos de Despliegue
Sistema completo para instalacion de 10.000 m2 con 500 activos:
| Componente |
Cant |
Costo Unit. |
Subtotal |
% |
| BLE tags (CR2032, 3 anos) |
500 |
$8 |
$4.000 |
18% |
| Gateways dedicados |
20 |
$120 |
$2.400 |
11% |
| Servidor edge |
1 |
$800 |
$800 |
4% |
| Red + cableado |
1 |
$1.500 |
$1.500 |
7% |
| Cloud (ano 1) |
1 |
$3.600 |
$3.600 |
16% |
| Licencias software (ano 1) |
1 |
$5.000 |
$5.000 |
23% |
| Instalacion + comisionado |
1 |
$3.000 |
$3.000 |
14% |
| Repuestos (10%) |
– |
– |
$640 |
3% |
| Survey RF + calibracion |
1 |
$1.200 |
$1.200 |
5% |
| Total Ano 1 |
$22.140 |
100% |
Costo por activo: $22.140 / 500 = $44,28 (Ano 1), $8.640 / 500 = $17,28/ano (recurrente). Comparado con RFID ($60-120/activo) y Wi-Fi RTLS ($80-150/activo), es mas economico.
9. Benchmarks de Produccion
| Metrica |
Hospital (200 tags, 8GW) |
Almacen (500 tags, 20GW) |
Fabrica (1000 tags, 15GW) |
| Captura de escaneo |
98,2% |
96,5% |
94,1% |
| Precision (mediana) |
3,2 m |
4,8 m |
5,5 m |
| Latencia E2E (p95) |
2,8 s |
4,1 s |
5,3 s |
| Uptime GW |
99,7% |
99,2% |
98,8% |
| Datos cloud/mes |
4,2 GB |
18,7 GB |
24,3 GB |
| Falsos cambios zona |
0,8% |
2,1% |
3,5% |
| Vida bateria (mediana) |
31 meses |
28 meses |
26 meses |
10. Consideraciones de Escalado
| Escala |
Tags |
GW |
Edge |
Cloud |
Reto |
| Pequeno |
1-100 |
1-5 |
GW unico |
VPS unico |
Costo-eficiencia |
| Medio |
100-1.000 |
5-30 |
Servidor edge |
VPS+Redis+TSDB |
Brechas cobertura |
| Grande |
1.000-5.000 |
30-100 |
Multi-edge |
Cluster LB |
Coord. edge-edge |
| Enterprise |
5.000-50.000 |
100-500 |
Clusters regionales |
K8s+TSDB distribuido |
Agreg. multi-sitio |
11. Errores Comunes de Arquitectura
| Error |
Sintoma |
Causa |
Solucion |
| Cloud procesa todo |
Alta latencia, alto costo |
Sin filtrado edge |
Mover dedup + suavizado al edge |
| 1 GW por zona |
Huecos de cobertura |
Minimizar GW |
30-50% solapamiento |
| HTTP para todo |
CPU spike, perdida |
TCP handshake |
MQTT persistente |
| Sin buffer offline |
Brechas de datos |
Fire-and-forget |
SQLite buffer + replay |
| RSSI crudo |
Saltos 5-10 m |
Sin suavizado |
Exponencial alpha=0,3 |
| Sin dwell timer |
Falsos cambios zona |
Flicker cobertura |
30s minimo dwell |
| GW sobre-provisionado |
Datos redundantes |
Mas = mejor |
30-50% solapamiento |
| Sin gestion tags |
Tags fantasma |
Tags muertos no removidos |
Auto-archivar 24h silencio |
13. Resumen
Un sistema de rastreo de activos BLE en produccion tiene exito o fracasa por su infraestructura, no por sus tags. El BLE tag es el componente mas barato y simple del stack. La red de gateways, el pipeline de filtrado edge, el transporte de datos y el backend cloud determinan si el sistema entrega precision de 3 metros con latencia de 2 segundos o precision de 10 metros con latencia de 30 segundos. Los principios de arquitectura son claros: filtrar temprano y agresivamente en el edge, usar MQTT para transporte, bufferar para operacion offline y calibrar la estimacion de ubicacion por zona.