Construire un systeme de suivi d’actifs avec BLE tag ne consiste pas a choisir la bonne etiquette. Il s’agit de l’infrastructure qui recoit, filtre, transporte et stocke les donnees de centaines ou milliers d’etiquettes dispersées dans une installation. L’etiquette est un emetteur simple ; l’intelligence reside dans le reseau de passerelles, le processeur edge et le backend cloud. Cet article decompose l’architecture complete du systeme, de la reception radio au tableau de bord, avec des tableaux de selection materielle, des algorithmes de filtrage, des schemas de pipeline de donnees et des modeles de couts de deploiement bases sur des deploiements en production dans des hopitaux, entrepots et usines.
1. Vue d’Ensemble de l’Architecture Systeme
Un systeme de suivi d’actifs BLE en production a quatre couches, chacune avec des exigences distinctes de latence, debit et fiabilite :
| Couche |
Composants |
Latence |
Volume |
Impact Panne |
| T1: Couche Tags |
BLE tags (centaines a milliers) |
N/A (broadcast seul) |
~30 octets/tag/event |
Actif individuel perdu |
| T2: Couche Passerelle |
Scanners BLE (5-50) |
100-500 ms cycle |
~50 KB/s crete par GW |
Zone perdue (10-50 tags) |
| T3: Couche Edge |
Serveur local ou appliance |
1-5 s traitement |
~200 KB/s agrege |
Suivi retarde, non perdu |
| T4: Couche Cloud |
Backend, BD, dashboard |
1-10 s bout-en-bout |
~500 KB/s soutenu |
Lacune donnees historiques |
L’erreur d’architecture la plus courante est de traiter la passerelle comme un simple relais qui transmet les paquets BLE bruts au cloud. Avec 500 tags a intervalles de 1 seconde et 10 passerelles, ce sont 5.000 paquets par seconde qui frappent l’endpoint d’ingestion cloud, chacun contenant des lectures RSSI dupliquees de zones de couverture chevauchantes. Le filtrage edge n’est pas une optimisation ; c’est une exigence.
2. Selection Materielle de Passerelle
| Plateforme |
Puce BLE |
CPU |
RAM |
Puissance |
Cout BOM |
Pour |
| Basee ESP32 |
ESP32 (dual-mode) |
240 MHz Xtensa x2 |
520 KB SRAM |
2,5W (WiFi+BLE) |
$3-5 |
Petits sites, WiFi |
| Raspberry Pi + USB |
nRF52840 dongle |
1,4 GHz ARM A72 x4 |
1-4 GB |
5-7W |
$45-60 |
R&D, prototypage |
| Passerelle dediee |
nRF52832/52840 + ESP32 |
ESP32 240MHz + nRF52 |
520KB + 256KB |
2-3W |
$15-25 |
Deploiements production |
| Passerelle industrielle (Linux) |
CC2640R2 + WiFi/LTE |
ARM Cortex-A7 1GHz |
512 MB |
5-15W |
$200-400 |
Environnements durs, cellulaire |
2.1 ESP32 comme Passerelle : Capacites et Limites
L’ESP32 est la plateforme passerelle la plus courante pour les deploiements sensibles aux couts car il integre WiFi et BLE. Cependant, le controleur BLE partage la radio 2,4 GHz entre WiFi et BLE, ce qui signifie qu’il ne peut pas scanner BLE pendant qu’il transmet WiFi :
| Activite WiFi |
Trou de Scan BLE |
Perte (1s) |
Perte (500ms) |
| Inactif |
0 ms |
0% |
0% |
| MQTT publish (toutes 5s) |
~15 ms/trou |
0,3% |
0,6% |
| WiFi streaming (continu) |
~50 ms/trou |
1,0% |
2,0% |
| OTA update |
~200 ms/trou |
5-8% |
10-15% |
2.2 Architecture de Passerelle Dediee
Les passerelles de production couplent typiquement un nRF52 (scanner BLE dedie) avec un ESP32 (WiFi/CPU). Le nRF52 execute un scan actif continu et transmet les paquets via UART/SPI a l’ESP32, qui gere le filtrage, la mise en tampon et la communication cloud. Ce design double puce elimine totalement la contention radio.
# Cote nRF52 : scanner BLE continu
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))
# Cote ESP32 : recevoir, filtrer, upload par lot
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 Placement des Passerelles et Couverture
| Niveau Precision |
GW/100m2 |
Espacement |
Cout/m2 |
Cas d’Usage |
| Presence (piece) |
0,5-1,0 |
10-15 m |
$0,15-0,30 |
Presence par zone |
| Position grossiere (3-5 m) |
2-4 |
5-8 m |
$0,60-1,20 |
Suivi d’allee |
| Position fine (1-2 m) |
6-10 |
3-5 m |
$1,80-3,00 |
Suivi d’instruments |
| Sub-metre (0,5 m) |
15-25 |
2-3 m |
$4,50-7,50 |
Audit haute valeur |
3. Strategie de Scan BLE
3.1 Scan Actif vs. Passif
| Parametre |
Scan Passif |
Scan Actif |
| Envoie SCAN_REQ |
Non |
Oui |
| Recoit SCAN_RSP |
Non |
Oui (jusqu’a 31 octets extra) |
| Consommation |
Plus basse (Rx seul) |
Plus haute (Tx + Rx) |
| Donnees disponibles |
31 octets |
62 octets |
3.2 Fenetre et Intervalle de Scan
| Intervalle |
Fenetre |
Duty Cycle |
Capture (1s) |
Capture (500ms) |
| Continu |
Continu |
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 Filtrage des Doublons au Niveau Radio
| Mode |
Doublons |
Paquets/s (500 tags, 1s, 10GW) |
CPU GW |
| Sans filtrage |
Tous |
~15.000 |
Eleve |
| Dedup controleur |
1/tag/cycle |
~500 |
Bas |
| Dedup application |
1/tag/fenetre |
~500 |
Bas-Moyen |
4. Filtrage Edge
4.1 Deduplication Multi-Passerelle
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 Lissage RSSI et Rejet des Valeurs Aberrantes
| Filtre |
Fenetre |
Latence |
Reduction Variance |
Complexite |
| Brut (sans filtre) |
1 |
0 s |
0% |
Aucune |
| Moyenne mobile |
5 |
2-5 s |
~55% |
Bas |
| Lissage exponentiel |
Infini |
1-3 s |
~50% |
Bas |
| Median |
3-7 |
1-3 s |
~65% |
Moyen |
| Kalman |
Adaptatif |
0,5-2 s |
~70% |
Eleve |
4.3 Transmission Basee sur Evenements
| Strategie |
Paq/Tag/Heure |
BW Cloud (500 tags) |
Cas d’Usage |
| Chaque scan (1s) |
3.600 |
~14 MB/h |
RTLS sous-seconde |
| Toutes 5s (lot) |
720 |
~2,8 MB/h |
Suivi standard |
| Changement zone seul |
~5-20 |
~40 KB/h |
Presence par piece |
| Seuil + heartbeat |
~2-10 |
~20 KB/h |
Alertes temperature |
5. Conception de Pipeline de Donnees
5.1 Comparaison des Protocoles de Transport
| Protocole |
Overhead |
Fiabilite |
Latence |
Puissance GW |
Pour |
| HTTP POST (JSON) |
~400 octets |
TCP garantit |
100-500 ms |
Eleve |
Petits deploiements |
| MQTT (QoS 1) |
~20 octets |
TCP + ACK |
50-200 ms |
Bas |
Deploiements production |
| UDP (custom) |
~8 octets |
Aucune |
10-50 ms |
Minimal |
RTLS temps reel, LAN |
| LoRaWAN |
~13 octets |
Confirme |
1-10 s |
N/A |
Sites distants sans WiFi |
5.2 Structure des Topics MQTT
# Hierarchie de topics MQTT
# Format : 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 octets)
{
"mac": "AA:BB:CC:DD:EE:01",
"rssi": -67,
"gw": "gw-01",
"ts": 1722422400000,
"bat": 85,
"temp": 23.5,
"seq": 4823
}
5.3 Schema de Donnees et Stockage
| Store |
Technologie |
Donnees |
Retention |
Requete |
| Time-series (hot) |
InfluxDB / TimescaleDB |
Evenements bruts |
7-30 jours |
Plage par tag + temps |
| Time-series (cold) |
S3 / Parquet |
Evenements agreges |
1-5 ans |
Analytics batch |
| Relationnel |
PostgreSQL / MySQL |
Metadonnees, zones |
Permanent |
CRUD, jointures |
| Cache |
Redis |
Derniere position |
TTL 5 min |
Lookup sub-ms |
5.4 Dimensionnement du Stockage
# 500 tags, intervalle 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/jour
bytes_per_year = 691 * 365 # = ~252 GB (brut)
compressed_per_year = 252 / 5 # = ~50 GB (Parquet 5:1)
total_storage_year = 50 * 1.4 # = ~70 GB (avec overhead BD)
6. Estimation de Position a l’Edge
| Algorithme |
GW Min |
Precision |
CPU Edge |
Calibration |
Pour |
| Proximite (RSSI max) |
1 |
Piece (5-10m) |
Minimal |
Aucune |
Presence simple |
| Centroide pondere |
3+ |
3-5 m |
Bas |
Positions GW |
Zones ouvertes |
| Trilateration |
3+ |
2-4 m |
Moyen |
Exposant path-loss par zone |
Entrepots, couloirs |
| Fingerprinting (kNN) |
4+ |
1-3 m |
Moyen-Eleve |
Survey RF complet |
Interieurs complexes |
| BLE AoA |
1 (antenne array) |
0,5-1 m |
Eleve |
Calibration phase antenne |
Actifs haute valeur |
6.1 Algorithme du Centroide Pondere
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. Fiabilite Systeme et Failover
7.1 Monitoring de Sante des Passerelles
| Metric |
Normal |
Alerte |
Intervalle |
| Paquets/min |
50-500 |
< 10 ou > 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% |
Quotidien |
| Dernier heartbeat |
< 30 s |
> 120 s |
30 s |
7.2 Tampon en Cas de Perte de Connexion Edge-Cloud
| Max Indisponibilite |
Tampon (500 tags, 5s) |
Support |
| 15 min |
~4,3 MB |
RAM |
| 1 heure |
~17 MB |
RAM/SD |
| 4 heures |
~69 MB |
SD/eMMC |
| 24 heures |
~415 MB |
SSD/eMMC |
8. Modele de Cout de Deploiement
Systeme complet pour installation de 10.000 m2 avec 500 actifs :
| Composant |
Qte |
Cout Unitaire |
Sous-total |
% |
| BLE tags (CR2032, 3 ans) |
500 |
$8 |
$4.000 |
18% |
| Passerelles dediees |
20 |
$120 |
$2.400 |
11% |
| Serveur edge |
1 |
$800 |
$800 |
4% |
| Reseau + cablage |
1 |
$1.500 |
$1.500 |
7% |
| Cloud (annee 1) |
1 |
$3.600 |
$3.600 |
16% |
| Licences logiciel (annee 1) |
1 |
$5.000 |
$5.000 |
23% |
| Installation + comissioning |
1 |
$3.000 |
$3.000 |
14% |
| Pieces de rechange (10%) |
– |
– |
$640 |
3% |
| Survey RF + calibration |
1 |
$1.200 |
$1.200 |
5% |
| Total Annee 1 |
$22.140 |
100% |
Cout par actif : $22.140 / 500 = $44,28 (Annee 1), $8.640 / 500 = $17,28/an (recurrent). Plus economique que RFID ($60-120/actif) et Wi-Fi RTLS ($80-150/actif).
9. Benchmarks de Production
| Metric |
Hopital (200 tags, 8GW) |
Entrepot (500 tags, 20GW) |
Usine (1000 tags, 15GW) |
| Taux de capture scan |
98,2% |
96,5% |
94,1% |
| Precision (mediane) |
3,2 m |
4,8 m |
5,5 m |
| Latence E2E (p95) |
2,8 s |
4,1 s |
5,3 s |
| Uptime GW |
99,7% |
99,2% |
98,8% |
| Donnees cloud/mois |
4,2 GB |
18,7 GB |
24,3 GB |
| Faux changements zone |
0,8% |
2,1% |
3,5% |
| Duree vie batterie (mediane) |
31 mois |
28 mois |
26 mois |
10. Considerations de Mise a l’Echelle
| Echelle |
Tags |
GW |
Edge |
Cloud |
Defi |
| Petit |
1-100 |
1-5 |
GW unique |
VPS unique |
Cout-efficacite |
| Moyen |
100-1.000 |
5-30 |
Serveur edge |
VPS+Redis+TSDB |
Trous de couverture |
| Grand |
1.000-5.000 |
30-100 |
Multi-edge |
Cluster LB |
Coord. edge-edge |
| Enterprise |
5.000-50.000 |
100-500 |
Clusters regionaux |
K8s+TSDB distribue |
Aggregation multi-site |
11. Erreurs Courantes d’Architecture
| Erreur |
Symptome |
Cause |
Solution |
| Cloud traite tout |
Haute latence, cout eleve |
Pas de filtrage edge |
Dedup + lissage a l’edge |
| 1 GW par zone |
Trous de couverture |
GW minimise |
30-50% de chevauchement |
| HTTP pour tout |
Pics CPU, perte |
TCP handshake |
MQTT persistant |
| Pas de tampon offline |
Lacunes de donnees |
Fire-and-forget |
Tampon SQLite + replay |
| RSSI brut pour position |
Sauts de 5-10 m |
Pas de lissage |
Exponentiel alpha=0,3 |
| Pas de timer de sejour |
Faux changements zone |
Flicker de couverture |
30s sejour minimum |
| GW surprovisionne |
Donnees redondantes |
Plus = mieux |
30-50% de chevauchement |
| Pas de gestion des tags |
Tags fantomes |
Tags morts non retires |
Auto-archivage 24h silencieux |
13. Resume
Un systeme de suivi d’actifs BLE en production reussit ou echoue par son infrastructure, pas par ses tags. Le BLE tag est le composant le moins cher et le plus simple de la pile. Le reseau de passerelles, le pipeline de filtrage edge, le transport de donnees et le backend cloud determinent si le systeme livre une precision de 3 metres a 2 secondes de latence ou une precision de 10 metres a 30 secondes de latence. Les principes d’architecture sont clairs : filtrer tot et agressivement a l’edge, utiliser MQTT pour le transport, mettre en tampon pour le fonctionnement hors ligne et calibrer l’estimation de position par zone.