═══════════════════════════════════════════════════════════════════════════
COMPTE RENDU DE PROJET — BORNE DE SAUVEGARDE FREECAD SUR CLÉ USB
Raspberry Pi • Hotspot WiFi • Portail Captif • Upload HTTP • USB
FabLab DropboxAteliers — 2025/2026
═══════════════════════════════════════════════════════════════════════════
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. INTRODUCTION ET OBJECTIFS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CONTEXTE :
Les utilisateurs du FabLab travaillent sur FreeCAD pour concevoir des
pièces 3D. Le problème était la sauvegarde des fichiers : pas de support
de stockage commun, pas de connexion internet fiable, et des fichiers
perdus régulièrement.
OBJECTIFS :
- Créer un point d'accès WiFi autonome sur Raspberry Pi
- Afficher automatiquement une page web dès la connexion (portail captif)
- Permettre l'upload de fichiers FreeCAD depuis n'importe quel appareil
- Copier automatiquement les fichiers sur toutes les clés USB branchées
- Fonctionner sans connexion internet ni configuration utilisateur
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2. MATÉRIEL UTILISÉ
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MATÉRIEL PHYSIQUE :
• Raspberry Pi 4 (ou 3B+) → serveur central
• Carte microSD 16 Go minimum → système d'exploitation
• Une ou plusieurs clés USB → stockage des fichiers FreeCAD
• Câble alimentation USB-C 5V/3A
• Optionnel : écran HDMI pour la configuration initiale
LOGICIELS :
• Debian 13 (Trixie) pour Raspberry Pi
• Python 3.13 → serveur HTTP
• hostapd → création du point d'accès WiFi
• dnsmasq → DHCP (distribue les IP) + DNS (portail captif)
• NetworkManager → gestion des interfaces réseau
• iptables → redirection du trafic HTTP
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
3. ARCHITECTURE DU SYSTÈME
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SCHÉMA SIMPLIFIÉ :
[ Téléphone / Tablette / PC ]
|
| WiFi "FabLab-FreeCAD"
↓
[ Raspberry Pi — 192.168.4.1 ]
├── hostapd → diffuse le réseau WiFi
├── dnsmasq → donne une IP aux clients + redirige DNS
├── server.py → sert la page web + traite les uploads
└── iptables → force l'ouverture du portail captif
|
| Copie fichiers
↓
[ Clés USB — /media/user/THOMAS G ]
└── FreeCAD_Files/
├── mon_projet.FCStd
├── piece.STEP
└── ...
FONCTIONNEMENT RÉSEAU :
1. L'utilisateur se connecte au WiFi "FabLab-FreeCAD"
2. dnsmasq lui attribue une IP (ex: 192.168.4.15)
3. L'appareil vérifie la connexion internet (requête automatique)
→ Android : GET /generate_204
→ iOS : GET /hotspot-detect.html
→ Windows : GET /ncsi.txt
4. server.py intercepte et répond 302 → http://192.168.4.1/
5. Le navigateur ouvre automatiquement la page d'upload
6. L'utilisateur dépose ses fichiers
7. server.py copie les fichiers sur toutes les clés USB branchées
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4. FICHIERS DU PROJET
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Le projet contient 3 fichiers à placer dans le même dossier :
~/Documents/Python-file-upload-server-main/
├── server.py
├── index.html
└── setup_captive_portal.sh
── server.py ─────────────────────────────────────────────────────────────
Rôle : cœur du projet — serveur HTTP Python
Fonctionnalités :
• Détecte les clés USB montées (3 méthodes : /media/, lsblk, /mnt/)
• Intercepte les requêtes de portail captif (Android/iOS/Windows)
• Parse les fichiers uploadés en multipart/form-data (SANS module cgi)
• Copie chaque fichier dans FreeCAD_Files/ sur chaque clé USB
• Expose /api/usb → liste JSON des clés disponibles
IMPORTANT : écrit sans "import cgi" car ce module a été supprimé
en Python 3.13. Le parsing multipart est fait manuellement avec
les modules natifs re, os, et des opérations sur les bytes.
Détection USB — triple méthode :
1. glob('/media/*/*') → standard Raspberry Pi avec interface graphique
2. lsblk --json → détecte tran=usb ou montage dans /media/ /mnt/
3. glob('/mnt/*') → fallback pour les montages manuels
── index.html ────────────────────────────────────────────────────────────
Rôle : interface utilisateur web (portail captif)
Fonctionnalités :
• Affiche les clés USB disponibles avec espace libre (barre de progression)
• Zone drag & drop pour déposer les fichiers
• Supporte : .FCStd .STEP .STP .IGES .STL .OBJ .BRep .FCMacro
• Barre de progression pendant l'upload avec vitesse en MB/s
• Affiche les résultats : quel fichier → quelle clé USB → succès/erreur
• Rafraîchissement automatique des clés USB toutes les 15 secondes
• Design responsive (fonctionne sur téléphone, tablette, PC)
── setup_captive_portal.sh ───────────────────────────────────────────────
Rôle : installation automatique complète (une seule exécution)
Ce script réalise en 6 étapes :
[1/6] Installe hostapd, dnsmasq, iptables
[2/6] Isole wlan0 de NetworkManager (évite les conflits)
[3/6] Configure l'IP fixe 192.168.4.1 sur wlan0
[4/6] Configure hostapd (WiFi FabLab-FreeCAD, WPA2)
[5/6] Configure dnsmasq (DHCP + DNS captif)
[6/6] Arrête lighttpd + crée le service systemd freecad-usb-server
Usage : sudo bash setup_captive_portal.sh
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
5. INSTALLATION PAS À PAS (depuis zéro)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ÉTAPE 1 — Copier les fichiers sur le Raspberry Pi
─────────────────────────────────────────────────
Créez le dossier et placez-y les 3 fichiers du projet :
cd ~/Documents/Python-file-upload-server-main
- → copiez server.py, index.html, setup_captive_portal.sh ici
ÉTAPE 2 — Lancer le script d'installation (TOUT configure automatiquement)
───────────────────────────────────────────────────────────────────────────
sudo bash setup_captive_portal.sh
Durée : environ 1 à 2 minutes.
À la fin, le script affiche l'état de chaque service.
Le réseau WiFi "FabLab-FreeCAD" est maintenant diffusé.
ÉTAPE 3 — Probleme du montage automatique des clés USB
─────────────────────────────────────────────────────────
Sans interface graphique, les clés USB ne se montent pas seules.
Il faut installer une OS avec interface graphique léger dans ce cas
ÉTAPE 4 — Vérifier que tout fonctionne
───────────────────────────────────────
Vérifier les services :
sudo systemctl status hostapd
sudo systemctl status dnsmasq
sudo systemctl status freecad-usb-server
Vérifier l'IP de wlan0 :
ip addr show wlan0
→ Doit afficher : inet 192.168.4.1/24
Tester avec un téléphone :
1. Connectez-vous au WiFi "FabLab-FreeCAD" (mot de passe: fablab1234)
2. La page d'upload doit s'ouvrir automatiquement
3. Les clés USB doivent apparaître dans la page
4. Uploadez un fichier et vérifiez qu'il apparaît sur la clé USB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
6. PROBLÈMES RENCONTRÉS ET SOLUTIONS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PROBLÈME 1 — Port 80 déjà utilisé (lighttpd)
─────────────────────────────────────────────
Erreur : OSError: [Errno 98] Address already in use
Cause : lighttpd était installé et utilisait déjà le port 80
Solution :
sudo systemctl stop lighttpd
sudo systemctl disable lighttpd
→ Le script setup le fait automatiquement désormais.
PROBLÈME 2 — Clé USB non montée automatiquement
─────────────────────────────────────────────────
Erreur : page web affiche "Aucune clé USB détectée"
Cause : sans interface graphique, Debian 13 ne monte pas les clés USB.
La clé était visible dans lsblk mais sans MOUNTPOINT.
Solution : installer une OS avec interface graphique léger car c est le meilleur solution
PROBLÈME 3 — Conflit NetworkManager / hostapd
──────────────────────────────────────────────
Erreur : "wlan0: Could not connect to kernel driver"
Cause : NetworkManager prenait le contrôle de wlan0 et empêchait
hostapd de l'utiliser.
Solution : exclure wlan0 de NetworkManager :
sudo nano /etc/NetworkManager/conf.d/no-wlan0.conf
Contenu :
[keyfile]
unmanaged-devices=interface-name:wlan0
PROBLÈME 4 — IP fixe manquante sur wlan0
──────────────────────────────────────────
Erreur : clients bloqués sur "Obtention de l'adresse IP" en boucle
Cause : wlan0 n'avait pas d'adresse IP fixe donc dnsmasq ne
pouvait pas distribuer d'adresses.
Solution :
sudo ip addr add 192.168.4.1/24 dev wlan0
sudo ip link set wlan0 up
+ Configuration permanente dans /etc/network/interfaces.d/wlan0-hotspot
PROBLÈME 5 — Module Python 'cgi' supprimé en Python 3.13
──────────────────────────────────────────────────────────
Erreur : ModuleNotFoundError: No module named 'cgi'
Cause : le module cgi a été supprimé de Python 3.13.
Le paquet legacy-cgi n'était pas disponible sans internet.
Solution : réécriture complète du parseur multipart/form-data en Python
pur, sans aucune dépendance externe (uniquement re + os).
PROBLÈME 6 — dnsmasq en conflit avec NetworkManager
─────────────────────────────────────────────────────
Erreur : dnsmasq refusait de démarrer (port 53 déjà utilisé)
Cause : NetworkManager lance son propre mini-dnsmasq en interne.
Solution :
sudo systemctl stop NetworkManager
sudo systemctl restart dnsmasq
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
7. COMMANDES UTILES AU QUOTIDIEN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GESTION DES SERVICES :
sudo systemctl status freecad-usb-server → état du serveur web
sudo systemctl restart freecad-usb-server → redémarrer le serveur
sudo journalctl -u freecad-usb-server -f → logs en direct
sudo systemctl status hostapd → état du WiFi
sudo systemctl status dnsmasq → état du DHCP/DNS
RÉSEAU :
ip addr show wlan0 → vérifier l'IP (doit être 192.168.4.1)
nmcli dev status → état des interfaces
CLÉS USB :
lsblk -o NAME,MOUNTPOINT,TRAN,LABEL,SIZE → lister les périphériques
ls /media/user/ → voir les clés montées
sudo mount /dev/sda1 /media/user/MA_CLE → monter manuellement
RÉINSTALLATION COMPLÈTE :
cd ~/Documents/Python-file-upload-server-main
sudo bash setup_captive_portal.sh
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
8. CONFIGURATION FINALE DU SYSTÈME
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
INFORMATIONS RÉSEAU :
Nom WiFi (SSID) : FabLab-FreeCAD
Mot de passe : fablab1234
IP du Raspberry : 192.168.4.1
Plage IP clients : 192.168.4.10 → 192.168.4.100
Page d'accueil : http://192.168.4.1
FICHIERS DE CONFIGURATION CRÉÉS :
/etc/hostapd/hostapd.conf → config WiFi
/etc/default/hostapd → pointe vers hostapd.conf
/etc/dnsmasq.conf → DHCP + DNS captif
/etc/NetworkManager/conf.d/no-wlan0.conf → exclut wlan0 de NM
/etc/network/interfaces.d/wlan0-hotspot → IP fixe persistante
/etc/systemd/system/freecad-usb-server.service → service au démarrage
/etc/udev/rules.d/99-usb-automount.rules → montage auto USB
/usr/local/bin/usb-mount.sh → script de montage
SERVICES QUI DÉMARRENT AUTOMATIQUEMENT AU BOOT :
hostapd → WiFi
dnsmasq → DHCP + DNS
freecad-usb-server → serveur web + upload USB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
9. CONCLUSION
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Le projet a été mené à bien malgré plusieurs obstacles techniques liés à
Debian 13 sur Raspberry Pi (suppression du module cgi en Python 3.13,
conflits NetworkManager/hostapd, montage USB sans interface graphique).
RÉSULTAT FINAL — La borne fonctionne ainsi :
✓ Diffuse un réseau WiFi "FabLab-FreeCAD"
✓ Ouvre automatiquement la page d'upload sur tout appareil connecté
✓ Accepte les fichiers FreeCAD (.FCStd, .STEP, .STL, .BRep, etc.)
✓ Copie les fichiers sur TOUTES les clés USB branchées
✓ Démarre automatiquement à chaque démarrage du Raspberry Pi
✓ Fonctionne sans connexion internet
✓ Aucune configuration requise pour l'utilisateur final
═══════════════════════════════════════════════════════════════════════════
FabLab — Raspberry Pi 4 — Debian 13 Trixie — 2025/2026
═══════════════════════════════════════════════════════════════════════════