Présentation du projet
Traject’air (aussi connu sous le nom BikeAir) est un projet de groupe développé sur deux années scolaires (2023-2025) au Lycée Sainte Céline de La Ferté-sous-Jouarre, par une équipe de 4 personnes : Jules (modélisation 3D du boîtier), Sharon (développement des composants), Eloan (site web et communication) et Thomas (application mobile).
L’objectif : créer une solution complète permettant de mesurer, visualiser et cartographier la qualité de l’air en temps réel depuis un vélo. Le projet combine une application mobile, un boîtier capteur embarqué sur Raspberry Pi, et un site web vitrine.
📥 Télécharger l’APK Voir le site web
1. Application mobile
L’application est le coeur du projet. Développée avec Vue.js 3, Ionic 8 et TypeScript, elle est compilée en application Android native via Capacitor.
Écran Carte (home.vue)
L’écran principal affiche une carte OpenStreetMap (via Leaflet) en plein écran. Quand le capteur est connecté, un marqueur coloré suit la position du vélo en temps réel. Derrière lui, un tracé polyligne se dessine avec une couleur qui change selon l’IQA mesuré à chaque point (vert = air propre, rouge = pollué).
En haut à gauche, une carte affiche l’IQA en direct avec un dégradé de couleur. En haut à droite, un chip indique l’état de la connexion Bluetooth. En bas, une légende rappelle l’échelle des couleurs IQA.
Écran Dashboard (dashboard.vue)
Le tableau de bord affiche les 6 mesures en direct sous forme de cartes avec barres de progression et indicateurs de seuil :
- PM2.5 et PM10 : particules fines en µg/m³, avec barre de remplissage et statut (Excellent / Modéré / Mauvais / Dangereux)
- CO₂ : dioxyde de carbone en ppm
- COV : composés organiques volatils (index)
- Température et Humidité : affichées avec des jauges circulaires SVG
En haut, une grande carte affiche l’IQA global avec un gradient de couleur et une icône qui change selon le niveau (visage heureux, alerte, danger). En bas, les statistiques de session : durée, nombre de points enregistrés et IQA moyen.
Autres écrans
- Paramètres : gestion de la connexion Bluetooth (appairage, reconnexion auto), notifications d’alerte quand l’IQA dépasse 100, mode sombre, choix de la langue (FR/EN), export des données et suppression de l’historique
- Contact : formulaire envoyé via EmailJS (sans backend)
- Avis : retours et notes des utilisateurs
Architecture du code
L’application suit une architecture par composables (pattern Vue 3) :
useBluetooth.ts: gère le cycle de vie Bluetooth (scan, connexion, réception des données via notifications BLE)useSensorData.ts: traitement et stockage des données capteursuseWebSocket.ts: connexion WebSocket en fallback si le Bluetooth n’est pas disponiblesensorStore.ts: store Pinia centralisé pour l’état global des capteurs- Les données des parcours sont persistées localement dans IndexedDB (via la lib
idb), ce qui permet de les consulter hors-ligne
2. Boîtier capteur (Raspberry Pi)
Le boîtier embarqué sur le vélo est un Raspberry Pi qui exécute un backend FastAPI (Python). Il lit les capteurs toutes les secondes et transmet les données à l’application.
Les 6 capteurs
| Capteur | Modèle | Mesure | Seuils |
|---|---|---|---|
| PM2.5 | SDS011 | Particules fines (µg/m³) | < 10 = Excellent, > 50 = Dangereux |
| PM10 | SDS011 | Particules grossières (µg/m³) | < 20 = Excellent, > 100 = Dangereux |
| CO₂ | MH-Z19 | Dioxyde de carbone (ppm) | < 800 = Excellent, > 2000 = Dangereux |
| COV | SGP30 | Composés organiques volatils (index) | < 100 = Excellent, > 300 = Dangereux |
| Température | BME280 | Température ambiante (°C) | — |
| Humidité | BME280 | Humidité relative (%) | — |
Le SensorManager centralise la lecture de tous les capteurs. Chaque capteur a sa propre classe (ex : PMSensor, CO2Sensor) avec un mode simulation pour tester sans le matériel physique.
Communication avec l’application
La Raspberry Pi envoie les données par deux canaux :
Bluetooth Low Energy (BLE) — canal principal :
- Le serveur BLE expose un service GATT avec un UUID dédié (
12345678-1234-5678-1234-56789abcdef0) - L’app s’abonne aux notifications de la caractéristique capteur
- À chaque seconde, la Raspberry envoie un paquet JSON via BLE contenant : les 6 valeurs capteurs, l’IQA calculé, la position GPS et un timestamp
- L’app décode le
DataViewreçu en UTF-8, puis parse le JSON
WebSocket — canal de secours (WiFi) :
- Endpoint
/wssur le serveur FastAPI (port 8000) - Même format de données JSON
- Utilisé quand le Bluetooth n’est pas disponible ou instable
API REST
Le backend expose aussi des endpoints REST :
GET /sensors/current— dernières valeurs capteursGET /sensors/iqa— IQA actuelGET /health— statut de chaque capteur (disponible ou non)GET /bluetooth/status— état du serveur BLE
Calcul de l’IQA
Le calculateur IQA utilise l’algorithme EPA (Environmental Protection Agency) avec interpolation linéaire par paliers. Pour chaque polluant (PM2.5, PM10, CO₂, COV), un sous-indice est calculé à partir de breakpoints définis. L’IQA final est le maximum de tous les sous-indices (c’est le polluant le plus présent qui détermine la qualité globale).
| IQA | Niveau | Couleur |
|---|---|---|
| 0-20 | Très faible | Cyan |
| 21-50 | Faible | Vert |
| 51-100 | Modéré | Orange |
| 101-150 | Élevé | Rouge |
| 151-250 | Très élevé | Violet |
| 251-500 | Danger | Violet foncé |
3. Site web vitrine
Le site trajectair.com est développé en HTML, CSS et JavaScript vanilla (sans framework). Il comporte 9 pages : accueil, à propos, actualités, carte interactive, contact, équipe, pollution de l’air, développement durable et mentions légales.
La page Carte intègre Leaflet avec géolocalisation du navigateur (fallback sur Paris), un champ de recherche d’adresse via l’API Nominatim (OpenStreetMap), et le calcul d’itinéraire avec Leaflet Routing Machine affiché en pointillés bleus.
Le site inclut aussi Google Analytics (via GTM), les liens vers les réseaux sociaux (Instagram, TikTok, YouTube, Discord), et un formulaire de contact.
Stack technique
| Technologie | Utilisation |
|---|---|
| Vue.js 3 | Framework frontend de l’application |
| Ionic 8 | Composants UI mobile (toolbar, menu, modals) |
| TypeScript | Typage statique dans toute l’app |
| Pinia | Store centralisé des données capteurs |
| Leaflet | Carte, marqueurs, tracés polyligne |
| Capacitor | Build APK Android natif |
| @capacitor-community/bluetooth-le | Communication Bluetooth BLE |
| IndexedDB (idb) | Stockage local des parcours hors-ligne |
| EmailJS | Envoi de formulaire sans backend |
| FastAPI | Serveur Python sur Raspberry Pi |
| dbus-next | Serveur GATT Bluetooth côté Raspberry |
| Pydantic | Validation des données capteurs |
| HTML/CSS/JS | Site web vitrine |
| Leaflet Routing Machine | Itinéraires sur le site web |
Réseaux sociaux
Le projet est aussi présent sur les réseaux :
- Instagram : @trajectair
- TikTok : @bike_air
- YouTube : @BikeAir77
Ce que j’ai appris
- Développement d’une application mobile hybride complète avec Vue.js, Ionic et Capacitor
- Communication Bluetooth Low Energy (GATT, notifications, décodage DataView)
- Conception d’une API REST et WebSocket avec FastAPI
- Intégration de capteurs matériels (SDS011, MH-Z19, SGP30, BME280) sur Raspberry Pi
- Calcul d’indices de qualité de l’air selon les normes EPA (interpolation par breakpoints)
- Cartographie interactive avec Leaflet : marqueurs dynamiques, tracés colorés, géolocalisation
- Stockage hors-ligne avec IndexedDB
- Gestion d’un projet sur 2 ans avec une équipe de 4 personnes