POC – Un Raspberry Pi sur un drone pour cartographier le Wi‑Fi (et visualiser la couverture) – Partie 1

Je travaille sur un projet perso assez fun (et très concret) : monter un Raspberry Pi Zero 2 W sur un drone pour scanner les réseaux Wi‑Fi visibles pendant le vol, enregistrer toutes les données en local, puis analyser à la maison sur une interface web avec carte.

L’idée n’est pas de “pirater” quoi que ce soit : l’objectif est de cartographier la couverture Wi‑Fi sur une zone donnée (ex. site / entreprise / terrain), avec une vue claire : où je capte bien, où le signal devient faible, et comment se répartissent les points d’accès.


Le concept : “Wi‑Fi + GPS + base de données”

Pendant le vol, on collecte deux types d’informations :

  • Wi‑Fi : SSID, BSSID (MAC), puissance du signal (RSSI), canal, chiffrement…
  • GPS : latitude, longitude, altitude, timestamp

À chaque “tick” (ex. toutes les 10 secondes), on fait un scan Wi‑Fi et on associe les résultats à la dernière position GPS valide.

Ensuite, toutes les mesures sont stockées dans une base locale (SQLite). À la maison, on lance une interface web qui permet de :

  • voir les réseaux sur une carte,
  • afficher une vue “couverture” (heatmap) en fonction du RSSI,
  • supprimer des réseaux non pertinents,
  • afficher des infos avancées (debug GPS/collecte).

Matériel utilisé

Raspberry Pi

  • Raspberry Pi Zero 2 W (léger, compact, suffisant pour du scan + SQLite + Flask)

GPS

  • Un module GPS UART (type NEO‑6M / NEO‑M8N)
  • Connexion via GPIO (UART)

Câblage (principe) :

  • VCC → 5V
  • GND → GND
  • TX GPS → RX Pi (GPIO15)
  • RX GPS → TX Pi (GPIO14)

Collecte : comment ça marche

Scan Wi‑Fi

Sur Linux, le scan se fait avec :

  • iw dev wlan0 scan

On parse ensuite la sortie pour extraire :

  • BSS / BSSID
  • SSID
  • signal: -xx dBm
  • channel
  • encryption (WPA2/WPA3/open…)

Lecture GPS

Le GPS arrive en trames NMEA sur /dev/serial0 (UART).
On lit typiquement des phrases GGA / RMC qu’on parse pour obtenir lat/lon/alt.

Modèle de stockage (SQLite)

Deux tables principales :

  • access_points
    • bssidssidencryptionchannel
    • first_seenlast_seen
      • une colonne vendor (constructeur, voir plus bas)
  • measurements
    • ap_id (clé vers l’AP)
    • timestamplatlonalt
    • rssi

L’intérêt : access_points = “référentiel” des réseaux, measurements = toutes les mesures dans l’espace/temps.


Interface Web : carte, liste, debug

Côté serveur :

  • Flask (API JSON + page HTML)

Côté client :

  • Leaflet + fond OpenStreetMap
  • Une vue “Points”
  • Une vue “Couverture” (heatmap)

Vue “Points”

  • Un marqueur par réseau (regroupé par SSID, donc un seul item même si plusieurs bornes/ BSSID)
  • Couleur selon le RSSI (vert/jaune/rouge)
  • Popup détaillée : SSID, BSSID, chiffrement, canal, RSSI, timestamp, nombre de bornes, constructeur

Vue “Couverture”

  • Une heatmap construite à partir de toutes les mesures
  • En gros : plus le RSSI est fort, plus c’est “chaud” (zone de bonne couverture)

Liste des réseaux

À gauche, une liste de tous les réseaux détectés.
Au clic, ça recentre la carte sur le marqueur.

Debug

Un panneau debug aide à vérifier rapidement :

  • fix GPS, nombre de satellites, lat/lon
  • “dernier scan”, erreurs éventuelles
  • compteurs en base

Bonus : identifier le constructeur via l’adresse MAC (OUI)

Chaque BSSID est une adresse MAC. Les 3 premiers octets (OUI) indiquent souvent le constructeur.

Exemple :

  • 8C:F8:13:… → constructeur X

J’ai ajouté une base offline de préfixes IEEE (fichier oui.txt officiel), parsée en oui_vendors.csv, puis importée dans une table SQLite vendors.

Ensuite, à chaque nouvel AP vu :

  • on extrait AA:BB:CC
  • on fait la correspondance OUI → constructeur
  • on stocke vendor dans access_points

Résultat : sur l’interface, on peut voir qui fabrique quoi (utile quand on veut distinguer box opérateur, matériel pro, etc.).


Démarrage automatique au boot (systemd)

Pour éviter de lancer à la main :

  • wifi-collector.service démarre la collecte au boot
  • wifi-web.service démarre l’interface web au boot

Comme ça :

  1. J’allume le Pi
  2. Il collecte automatiquement
  3. Je me connecte au web pour visualiser

Ce que j’ai appris (et les “pièges”)

  • Le GPS : dehors, ciel dégagé, le premier fix peut prendre plusieurs minutes.
  • Scanner Wi‑Fi et être connecté en Wi‑Fi : possible, mais parfois un peu instable si on scanne trop souvent.
  • SQLite + reset en live : supprimer la base pendant que des services la lisent/écrivent peut provoquer des erreurs I/O (donc on évite de “reset DB” en plein flux en prod).

Prochaines améliorations possibles

  • Filtrer par SSID / chiffrement / canal
  • Export CSV/JSON des données
  • Mode “sessions de vol” (une session = un vol)
  • Meilleure estimation de “portée” (modèle radio plus avancé, pas seulement heatmap)
  • Matériel Wi‑Fi dédié (dongle) pour limiter les micro‑coupures si besoin

Conclusion

Ce projet donne une manière très visuelle de répondre à une question simple :

“Où est-ce que ça capte bien, et où est-ce que ça commence à décrocher ?”

Avec un Pi Zero, un GPS UART, une base SQLite et une interface web légère, on obtient une cartographie utile, réutilisable, et facilement extensible.