AmbiSense est le projet IFT3225 de collecte et de consultation d'ambiances sonores. La phase 3 consolide l'application développée aux phases précédentes : elle ajoute des recommandations par ambiance et par heure, améliore la séparation des responsabilités, couvre les services par des tests, introduit des caches frontend et backend, optimise le chargement du client et déploie l'ensemble sur Render.
- Client React : https://ambisense-client.onrender.com
- API Express : https://ambisense-api.onrender.com
- Santé de l'API : https://ambisense-api.onrender.com/health
Les deux applications sont servies en HTTPS. Le client utilise l'URL publique de l'API et l'API limite CORS à l'origine du client déployé.
- Node.js 20.19 ou plus récent (ou Node.js 22.12+)
- MongoDB Atlas ou une instance MongoDB accessible
- phyphox pour effectuer les collectes réelles
À la racine du dépôt :
npm installCréer ensuite le fichier d'environnement à partir de l'exemple :
# Windows (PowerShell ou invite de commandes)
copy .env.example .env# macOS ou Linux
cp .env.example .envConfigurer ensuite .env sans publier ses valeurs :
MONGO_URI=mongodb+srv://...
PORT=1234
JWT_SECRET=une-longue-valeur-aleatoire
REMOTE_ACCESS=http://adresse-ip-du-telephone:8080
API_KEY=cle-api-du-dispositifUne valeur JWT peut être générée avec node -e "console.log(require('crypto').randomBytes(48).toString('hex'))".
La clé API n'est affichée qu'une fois par POST /devices; l'API conserve uniquement son empreinte SHA-256.
Si une valeur a déjà été publiée, il faut la remplacer dans Atlas et dans .env, même si le dépôt est privé.
Installer le client :
cd client
npm installCréer ensuite le fichier d'environnement du client :
# Windows (PowerShell ou invite de commandes)
copy .env.example .env# macOS ou Linux
cp .env.example .envLe fichier client/.env doit pointer vers l'API :
VITE_API_URL=http://localhost:1234Utiliser des terminaux séparés.
API, depuis la racine :
npm run devClient React :
npm --prefix client run devLe client est normalement accessible sur http://localhost:5173.
Pour une collecte phyphox, démarrer l'accès à distance dans l'application mobile, configurer REMOTE_ACCESS et API_KEY, puis lancer :
npm run bridgeDeux mécanismes coexistent :
x-api-keyidentifie un dispositif de collecte;Authorization: Bearer <jeton>identifie un compte utilisateur.
Le JWT est créé par l'API lors de l'inscription ou de la connexion. Le client le conserve et l'envoie automatiquement pour les actions protégées. Il ne faut donc pas générer de JWT manuellement pour utiliser le frontend.
| Méthode | Endpoint | Protection | Description |
|---|---|---|---|
POST |
/devices |
Publique | Créer un dispositif et recevoir sa clé API |
GET |
/devices |
Publique | Lister les dispositifs sans exposer leurs clés |
GET |
/devices/me |
Clé API | Consulter le dispositif courant |
POST |
/measurements |
Clé API | Enregistrer une mesure sonore |
POST |
/observations |
Clé API ou JWT | Enregistrer une observation |
GET |
/health |
Publique | Vérifier que l'API déployée répond |
GET |
/ambiance/:location/status |
Publique | Lire l'ambiance actuelle et sa classification |
GET |
/ambiance/:location/history?last=3 |
Publique | Lire l'historique agrégé en tranches horaires |
GET |
/ambiance/:location/quiet-hours |
Publique | Calculer les heures généralement les plus calmes |
GET |
/ambiance/:location/vibe |
Publique | Résumer les dernières observations humaines |
GET |
/places |
Publique | Lister les lieux, coordonnées et ambiances |
GET |
/places/:slug |
Publique | Consulter le portrait d'un lieu |
POST |
/places |
Clé API | Ajouter un lieu avec ses coordonnées |
POST |
/users |
Publique | Créer un compte |
POST |
/users/login |
Publique | Se connecter |
GET |
/users/me |
JWT | Consulter le compte connecté |
POST |
/users/logout |
JWT | Se déconnecter |
GET |
/users/me/observations |
JWT | Consulter ses observations |
GET |
/users/me/favorites |
JWT | Consulter ses lieux favoris |
POST |
/users/me/favorites/:placeId |
JWT | Ajouter un lieu à ses favoris |
DELETE |
/users/me/favorites/:placeId |
JWT | Retirer un lieu de ses favoris |
GET |
/recommendations?ambiance=calm&hour=14 |
Publique | Classer les lieux selon l'ambiance et l'heure souhaitées |
GET |
/ambiance/stream?location=... |
Publique | Recevoir les classifications en SSE (bonus) |
L'espace compte présente les observations du compte de la plus récente à la plus ancienne, en déduit les lieux visités sans doublons et permet de retirer un lieu favori. Un utilisateur connecté peut aussi ajouter ou retirer le lieu courant depuis son portrait d'ambiance.
Exemple d'ajout d'un lieu :
curl -X POST http://localhost:1234/places \
-H "Content-Type: application/json" \
-H "x-api-key: VOTRE_CLE" \
-d '{"name":"Bibliotheque","slug":"bibliotheque","locationKey":"biblio_jb","latitude":45.5017,"longitude":-73.5673}'name est le libellé public. locationKey doit correspondre au champ location envoyé dans les mesures et observations. Cette séparation permet de corriger un nom affiché sans casser les collecteurs existants. Les anciens lieux sans locationKey continuent d'utiliser leur nom comme repli.
L'historique regroupe les mesures en tranches de 5 minutes pour la période de 3 heures et de 60 minutes pour les périodes plus longues. Pour ne pas casser la phase 1, data et measurements contiennent les documents bruts; slices contient les moyennes utilisées par le graphe. Chaque tranche expose aussi le minimum, le maximum et le nombre de mesures. Une période sans mesure retourne 200 avec des tableaux vides et un compteur à zéro.
Le bridge lit un échantillon fourni par phyphox toutes les cinq secondes. Il conserve cette valeur ponctuelle au lieu de moyenner arbitrairement un lot côté bridge. Les moyennes utiles à la visualisation sont calculées ensuite par l'historique, avec le nombre, le minimum et le maximum pour garder le contexte.
Flux recommandé pour chacun des trois lieux :
- créer le dispositif avec
POST /deviceset copier la clé retournée dansAPI_KEY; - créer le lieu avec
POST /places, ses coordonnées et le mêmelocationKeyque le collecteur; - démarrer l'accès à distance phyphox et
npm run bridge; - vérifier la réception dans
/ambiance/:location/status, puis ajouter au besoin une observation depuis le frontend; - conserver au total au moins 12 nouvelles mesures réelles réparties sur 3 lieux.
Si phyphox est momentanément indisponible, un envoi manuel permet seulement de tester le pipeline : POST /measurements avec type, value, location et timestamp, ainsi que x-api-key. Cette solution de repli doit être identifiée comme manuelle et ne constitue pas une preuve de collecte physique.
Le script suivant ajoute un dispositif, des mesures réparties sur deux jours et quelques observations pour tester les écrans et les endpoints :
npm run seedCes données artificielles servent au développement. Elles ne remplacent pas les données réelles demandées pour la remise : au moins 12 nouvelles mesures réparties sur 3 lieux différents, recueillies avec phyphox.
Les mots de passe utilisateurs sont hachés, les comptes utilisent des JWT et les appareils sont recherchés par empreinte de clé. En local, Express et Vite servent en HTTP. En production, Render termine TLS pour les deux adresses HTTPS, CORS est limité par CLIENT_ORIGIN et les secrets sont stockés dans les variables d'environnement de l'hébergeur.
Les lectures publiques coûteuses sont mises en cache en mémoire (src/services/cache.js) pour éviter de recalculer la même réponse à chaque visiteur :
| Donnée | Clé | Durée de vie | Invalidation |
|---|---|---|---|
Historique /ambiance/:location/history |
history:<lieu>:<période>:<format> |
1 min | Nouvelle mesure du lieu |
Créneaux calmes /ambiance/:location/quiet-hours |
quiet-hours:<lieu> |
5 min | Nouvelle mesure du lieu |
Recommandations /recommendations |
recommendations:<ambiance>:<heure> |
5 min | Toute nouvelle mesure |
Une nouvelle mesure (POST /measurements) vide immédiatement les entrées concernées. Ne sont jamais mis en cache : les écritures (POST), l'authentification et les comptes, ni le flux SSE GET /ambiance/stream (temps réel par nature).
Le client conserve pendant 30 secondes les lectures publiques de lieux, d'historique, de créneaux calmes et de recommandations. Le cache est une Map en mémoire : il disparaît lorsque l'onglet est fermé et ne place aucune donnée dans localStorage ou sessionStorage.
La clé correspond à l'URL complète de la requête. Une entrée est supprimée à son expiration, un rechargement explicite ignore la copie, et une observation enregistrée avec succès vide les lectures publiques qui pourraient être devenues anciennes. Les requêtes authentifiées, les comptes, les favoris, les écritures et les réponses en erreur ne sont jamais mis en cache.
L'API est déployée comme service web Node. Le fichier render.yaml décrit sa construction, son démarrage, sa route de santé et ses variables.
- Créer un Web Service relié au dépôt (ou « New + » → « Blueprint » pour lire
render.yaml). - Build command :
npm install— Start command :npm start. - Variables d'environnement (onglet Environment, jamais dans le code) :
MONGO_URI,JWT_SECRET,CLIENT_ORIGIN(URL du frontend déployé),APP_TIMEZONE. Render fournitPORTautomatiquement ; le serveur écouteprocess.env.PORT. - Dans MongoDB Atlas, autoriser l'accès réseau depuis Render (
0.0.0.0/0ou les IP de sortie de Render). - Health check :
/health. Vérifier ensuite une route publique (/health,/places) et une route protégée (/users/meavec un JWT).
Le dossier client/ est déployé comme site statique Render :
- répertoire racine :
client; - commande de construction :
npm install && npm run build; - répertoire publié :
dist; - variable de construction :
VITE_API_URL=https://ambisense-api.onrender.com; - réécriture :
/*vers/index.htmlpour conserver les routes React lors d'un accès direct.
Adresses en ligne vérifiées :
Sur le plan gratuit, le service s'endort après inactivité : la première requête peut prendre quelques secondes à réveiller l'instance.
La mesure du build, l'optimisation appliquée et la comparaison avant/après sont
documentées dans docs/performance-frontend.md.
npm test
npm --prefix client test
npm --prefix client run lint
npm --prefix client run buildsrc/
bridge/ liaison avec phyphox
middlewares/ authentification des dispositifs et utilisateurs
models/ modèles Mongoose
repositories/ accès aux données des recommandations
routes/ endpoints Express
services/ logique métier, agrégation, cache et connexion MongoDB
scripts/ données de démonstration
tests/ tests de l'API
client/src/
components/ composants React réutilisables
context/ authentification partagée
hooks/ chargement des données
pages/ écrans de l'application
services/ appels vers l'API