IMA4 2017/2018 P5 : Différence entre versions
(→Semaine 8) |
(→Semaine 9) |
||
Ligne 430 : | Ligne 430 : | ||
* La largeur du pcb devra donc être en adéquation avec la largeur de la coque afin que tous les composants restent bien fixés lors des déplacements de l'utilisateur. | * La largeur du pcb devra donc être en adéquation avec la largeur de la coque afin que tous les composants restent bien fixés lors des déplacements de l'utilisateur. | ||
+ | |||
+ | * Le back-end est quasiment complété. Il ne manque qu'à le mettre sur le cloud. Pour cela, deux choix sont possibles après discussion avec nos enseignants : soit utiliser une plateforme tierce, soit utilisée une machine virtuelle fournie par Mr Redon. Il s'agira d'une décision à prendre par la suite, lorsque nous nous assurerons que l'API et le serveur websocket fonctionnent sans aucun soucis. | ||
+ | Nous avons également fini d'implémenter les méthodes retournant un tableau JSON des points les plus proches à un point passé en paramètre de l'URL. | ||
+ | |||
+ | * Nous avons complétés la connexion websocket sur l'application et commencés l'écriture du service android qui tournera en fond. Nous utiliserons un BroadcastReceiver afin de communiquer avec l'activité principale de l'application et afficher les valeurs reçues sur la carte. | ||
+ | Nous avons également beaucoup travaillés sur le design de l'application afin de faire en sorte que la compréhension du fonctionnement soit intuitive. | ||
==Semaine 10== | ==Semaine 10== |
Version du 9 mai 2018 à 12:57
Sommaire
Réseau de capteurs de pollution
Présentation générale
Description
Notre projet consiste à réaliser un réseau de capteurs de pollution. Ceux ci permettront, au travers d'une application web et d'une application mobile de visualiser le taux de pollution aux particules fines et polluants chimiques en différents endroits d'une carte. Le capteur devra communiquer en bluetooth avec un téléphone pour envoyer les données récoltées sur le serveur. Nous pourrons ensuite, si le temps nous le permet, ajouter une fonctionnalité permettant d'aider les utilisateurs à trouver les chemins les plus appropriés pour se déplacer en étant le moins exposé possible à la pollution. En effet, l'exposition prolongée à un taux élevé de particules fines réduit l'espérance de vie. Connaitre le taux de pollution est donc un enjeu majeur.
Scénario
Pedro est intolérant aux particules fines et est cependant un grand sportif. Jusqu’à maintenant, il se contentait de courir sur des tapis roulants dans sa salle de sport. Cependant, il se demandait chaque fois quand est-ce qu’il franchirait le pas et irait courir dehors. Cela tombe bien car sa copine vient de lui offrir un capteur de pollution miniature tenant dans sa poche qui lui permet de connaître les endroits non pollués où il peut courir. Des centaines d’utilisateurs l’utilisent en ce moment et leurs données sont renvoyées en temps réel sur la carte de pollution de la ville qui s’affiche sur son smartphone. Il peut également visualiser où se trouvent les personnes disposants du capteur si celles-ci ont décidé de l’autoriser. Dans une prochaine mise à jour, Pedro se réjouit d’avance de pouvoir utiliser son application comme un véritable GPS d’air pur : en rentrant son point de départ et sa destination, il pourra obtenir la meilleure route possible selon ses conditions de tolérance.
Objectifs
- Élaboration d'un capteur de pollution permettant de détecter différents polluants (particules fines, poussière, résidus de combustion) connecté au réseau LoRaWAN
- Création d'une application web permettant aux utilisateurs de visualiser les taux de pollution détectés par les capteurs en différents endroits de la ville et de pouvoir déterminer le chemin le plus approprié pour leurs déplacements.
- Création d'une application mobile avec les mêmes spécificités que le site web
- Élaboration d'un algorithme de machine learning permettant de déterminer le meilleur chemin selon des anciennes données dans le cas d'une panne des capteurs.
Analyse du projet
Positionnement par rapport à l'existant
- Site web évaluant la pollution sur Lille : https://air.plumelabs.com/fr/live/lille
- Site évaluant la pollution de l'air dans différentes villes de France : http://aqicn.org/map/france/
- Carte couleur en fonction de la pollution : http://www2.prevair.org/
- Application plume air report donnant la qualité de l'air dans la ville demandée ainsi que des astuces pour éviter la pollution : https://plumelabs.com/en/products/air-report
Analyse du premier concurrent : Bornes implantées dans la ville
Certaines bornes peuvent permettre d'obtenir la qualité de l'air en dans la ville en temps réel. Cependant, notre projet aura comme avantage de :
- permettre de connaître précisément le taux de pollution en tous les endroits de la ville et pas seulement en un endroit fixe.
- D'obtenir le taux de pollution sur son téléphone. Il n'y a donc pas besoin de se déplacer pour le connaître.
Analyse du second concurrent : Applications, sites web indiquant le taux de pollution
D'autres applications et sites web permettent d'obtenir un taux de pollution comme Plume : https://air.plumelabs.com/fr/live/lille Notre projet permettra cependant d'ajouter :
- La possibilité de connaître la pollution dans des endroits plus précis de la ville contrairement à Plume qui donne une valeur par ville.
- Permet à l'utilisateur de faire sa propre mesure à l'aide du capteur.
Scénario d'usage du produit ou du concept envisagé
Sur la page d'accueil: les informations générales sur la pollution :
- La moyenne journalière de pollution sur toute la ville
- L'évolution de la pollution moyenne sur la semaine, le mois, l'année... (graphique)
Dans les autres onglets :
- Une carte de la ville de Lille présentant le niveau de pollution en fonction des données relevées sur les capteurs.
- Une interface permettant à l'utilisateur de rentrer le trajet qu'il souhaite réaliser et qui lui renvoie le meilleur itinéraire
Réponse à la question difficile
Selon certaines documentations, le capteur perd en précision lorsqu'un souffle est appliqué sur le capteur. Il faudrait donc envisager un moyen pour protéger le capteur du vent afin d'obtenir la meilleure précision. Surtout en cas de placement des capteurs sur des véhicules.
Quelle quantité de données sera envoyée par le smartphone et quelle consommation aura le capteur de particule fine ?
- données doit contenir : la position GPS du capteur, l'heure de la mesure ainsi que la mesure. Cela correspond donc à quelques dizaines d'octets. En fonction du nombre de mesures faites par heure, on peut donc calculer la quantité de données envoyée par heure ou par jour.
- consommation de la carte :
- ESP32 : environ 100mA en actif et sinon 4mA en slow speed sleep
- module GPS : ?????
- En prenant une batterie de 2000mA pour ne pas qu'elle soit trop encombrante et en prenant en compte une consommation moyenne de 10mA, nous obtenons une autonomie de 140H. Ce qui correspond à 1 semaine d'autonomie.
Préparation du projet
Cahier des charges
Réalisation de la carte du capteur :
Polluants pouvant être analysés :
- Monoxyde de carbone
- Dioxyde de carbone
- Ozone
- Particules en suspension PM2.5 (particules de diamètre inférieurs à 2,5 micromètres),PM10
- Dioxyde de souffre
Choix techniques : matériel et logiciel
Capteur :
- ESP32 (https://www.amazon.fr/AZ-Delivery-NodeMCU-développement-dénergie-successeur/dp/B071P98VTG/ref=pd_cp_107_1?_encoding=UTF8&psc=1&refRID=Y7HFS1X1WQGBM9VCHXTW)
- Module GPS ( si nous ne voulons pas utiliser le GPS du smartphone )
- Batterie Lithium Ion (https://www.adafruit.com/product/258)
- Adaptateur micro USB
- HPMA115S0-XXX
La raspberry pi peut être remplacée par le module Particle Photon ( Lien [[1]] ) qui comprend un module de données cellulaires qui amortirait le cout d'un dongle. Le kit de développement de Particle comprend une batterie et une carte SIM prépayée ainsi que plusieurs accessoires supplémentaires. Il serait peut être plus raisonnable d'opter pour le kit.
Backend
- Base de données NoSQL : RethinkDB ou MongoDB
- Google maps API : service de localisation avec points de cheminements pour choisir le meilleur itinéraire https://developers.google.com/maps/documentation/directions/intro?hl=fr#Waypoints
- Jersey : pour l'API REST et le traitement en temps réel
- RabbitMQ pour le système publish/subscribe
Application mobile :
- Java/Kotlin
Application Web :
- Node/AngularJS : pour améliorer la fluidité du site.
- Bootstrap/Semantic UI : pour faciliter le développement
Liste des tâches à effectuer
Calendrier prévisionnel
Réalisation du Projet
Feuille d'heures
Tâche | Prélude | Heures S1 | Heures S2 | Heures S3 | Heures S4 | Heures S5 | Heures S6 | Heures S7 | Heures S8 | Heures S9 | Heures S10 | Heures S11 | Heures S12 | Total |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Choix du matériel | 2H | 1H | ||||||||||||
Analyse du projet + préparation oral | 6H | |||||||||||||
Création du Back-End de l'application et de l'appli web | 2H | 5H | 6H | 5H | 3H | |||||||||
Site web | 6H | 10H | 12H | 4H | 6H | |||||||||
Carte/coque capteur | 3H | 2H | 8H | 8H | 6H | 6H | ||||||||
Programme ESP32 | 4H | 3H | ||||||||||||
Documentation (rethinkDB, rabbitMQ) | 3H | 2H | 1H | |||||||||||
Documentation (Angular JS, facebook authentification, maps) | 1H | |||||||||||||
Documentation Android | 4H | 8H | 2H | 1H | ||||||||||
Travail sur l'application Android | 6H | 2H | 5H | 3H | 3H | |||||||||
Wiki | 1H | 1H | 1H | 1H | 1H | 1H | ||||||||
Informations/Interprétation mesures | 1H |
Prologue
- Préparation de l'oral :
Description du projet : quels sont les objectif à remplir, scénario d'usage permettant de se rendre compte de l'utilité du projet et analyse des concurrents pour connaître ce qui existe déjà et savoir ce que nous devons ajouter dans notre projet pour nous démarquer.
- Choix du matériel et des technologies utilisées
- Après l'oral : réponse à la question sur l'autonomie de la batterie ainsi que sur la quantité de données envoyées
Semaine 1
- Vérification du schéma électronique et de la carte permettant d'alimenter et de contrôler notre capteur.
Nous avons finalement changé de batterie. En effet, une batterie de 5V nous paraissait plus adaptée du fait que nous devons alimenter le microcontroleur en 3,7V et le capteur en 5V. Nous obtiendrons un meilleur rendement en réalisant une baisse de tension qu'une augmentation de tension. La batterie sera un peu plus volumineuse mais nous permettra de tenir plus longtemps. Nous avons donc ajouté un connecteur micro-usb que nous souderons sur la carte et qui nous permettra de l'alimenter en 5V.
Semaine 2
- Documentation sur la base de donnée rethinkDB afin de bien comprendre son fonctionnement ainsi que le gestionnaire de queue de message rabbitMQ.
Ces recherches vont nous permettre d'être plus efficace par la suite et de savoir quel est le meilleur moyen d'utiliser cette base de donnée.
Semaine 3
- Installation des environnements de travail sur nos ordinateurs ainsi que sur un serveur pour nous permettre de travailler tous les deux sur les mêmes données : tomcat pour le serveur java, rethinkDB pour la base de données.Mais nous avons eu un problème car l'espace disponible sur le serveur que nous possédons n'est pas suffisant.
Début de la programmation du code serveur : Mise en place de l'architecture temps-réel et mise en avant des problèmes à résoudre : documentation sur les queues et les websockets. Problème : réaliser un code en boucle infinie pour pousser les données vers la queue, ou uniquement garder une connection WS active ?
Semaine 4
- Création de la base de projet web. Nous avons désormais une base de projet tournant avec Node, angular, rethinkdb et avec les fonctionnalités basiques.
Nous avons également étudié la documentation qui va nous permettre d'implémenter une authentification du client via facebook par exemple et d'utiliser l'API de google maps.
- Durant la séance suivante, nous avons pu utiliser l'api de google maps pour obtenir leur carte sur notre site web. Nous avons pour cela dû nous créer une clé d'identification et insérer leur script dans la page. Puis nous avons ajusté celle ci afin qu'elle prenne l'ensemble de la largeur du site. Enfin, nous avons réussi à manipuler les marqueurs afin de pouvoir indiquer les endroits où des mesures de taux de pollution ont été effectuées. Pour le moment, ces positions ont été fixées manuellement. Mais nous modifierons prochainement le code afin que les données soient récupérées dans la base de données et affichées dynamiquement sur la carte.
- Réalisation des endpoints REST pour l'utilisateur, mise en place du code associé aux actions sur la base de donnée. Mise en place des moyens de sécurisation (JWT en particulier). Réalisation de testbench pour tester ce qui à été mentionné précédemment.
Début de la réalisation de la partie temps réel.
Semaine 5
- Ajout de la librairie semantic UI au projet web pour permettre un design plus agréable pour l'utilisateur mais aussi faciliter celui ci. Cependant, nous avons eu quelques problèmes pour faire cohabiter toutes les librairies sur le projet web. Nous avons donc recréé un projet Web fonctionnant avec du javascript classique plutôt que Angular afin d'avoir une interface fonctionnelle le plus rapidement possible. En effet, nous devrons pouvoir faire des tests avec le capteur lorsque nous recevrons les composants. Nous retenterons de faire fonctionner les différents modules tous ensemble sous angular à la fin du projet si le temps nous le permet.
- Ajout de l'apparition des fenêtres lorsque l'utilisateur clic sur les markers de google maps correspondants aux points de mesure de pollution. Ceux ci indiqueront le taux de pollution calculé pour chaque polluant, la date et l'heure de la mesure ainsi que l'adresse à laquelle elle a été prise. Enfin, nous afficherons le nom et la photo de la personne qui a pris la mesure si celui ci l'accepte.
Nous pourrons également ajouter la météo du moment où la mesure a été prise. En effet, celle ci peut influer sur la précision de la mesure.
- Nous pourrons également implémenter un système de vérification des mesures prises. Si une données est aberrante par rapport aux données prisent aux alentours par d'autres membres, nous ne la prendrons pas en compte.
Semaine 6
- Nous avons reçu une partie de notre commande de composants dont l'ESP32. Nous avons donc pu commencer à travailler sur celui ci. Pour le programmer, 3 choix s'offraient à nous :
- Le logiciel PlatformIO : https://platformio.org/
- Le framework esp-idf disponible sur github : https://github.com/espressif/esp-idf
- Le logiciel et langage arduino
Nous nous sommes penchés vers cette dernière solution qui étaient celle proposée dans la datasheet de notre composant sur sparkfun. Certaines sources menaient à penser que certaines fonctionnalités n'étaient pas encore implémentées dans le module de développement arduino. Cependant, le projet ayant bien avancé depuis la dernière année, les fonctionnalités dont nous avons besoin (bluetooth) semblent bien présentes. Nous avons donc suivi les quelques étapes décrites sur ce lien pour installer le module supplémentaire sur le logiciel arduino : https://learn.sparkfun.com/tutorials/esp32-thing-hookup-guide?_ga=1.189350435.90086807.1452767181#installing-the-esp32-arduino-core
Nous avons ensuite réalisé le programme permettant d'envoyer les données et de les recevoir via bluetooth sur l'ESP32. Pour cela, nous devons importer les librairies BLE sur arduino. Et au moyen du langage C++ avons défini des fonctions de callback. Celle ci signalent lorsqu'un appareil se connecte ou se déconnecte de l'ESP32. Et signalent également lorsqu'un caractère est reçu. Dans le code principal, nous envoyons un nombre flottant qui s'incrémente toutes les secondes. Et lorsqu'un caractère est reçu, il s'affiche.
Nous avons également commencé l'application android permettant de communiquer avec l'ESP32. Celle ci est pour l'instant minimaliste et ne permet que de se connecter à notre microcontrôleur, d'envoyer des données en appuyant sur un bouton ou d'en recevoir à l'aide d'un autre bouton. Cela nous a donc permis de vérifier que le système de communication bluetooth fonctionne. Pour réaliser notre application et faire fonctionner la librairie BLE bluetooth d'android, il ne faut pas oublier de demander les permissions pour le bluetooth et la localisation qui sont indispensables. Par la suite, nous modifierons l'application android pour n'avoir qu'un seul bouton pour demander une mesure et l'afficher. Le code de l'arduino lui devra se mettre en attente tant qu'un caractère précis n'est pas reçu. Puis, lors de sa réception, communiquera avec notre capteur de pollution pour récupérer les données et les envoyer sur l'application android.
Voici le résultat sur la vidéo suivante, qui démontre que la connexion entre notre microcontroleur et l'appli android fonctionne :
Quant au coté serveur, les appels permettant de récupérer l'ensemble des données de l'air ou plus de détails sur une donnée particulière ont été réalisés. Nous avons également mis en place le serveur websocket. Plus de documentation est nécessaire car nous ne savons toujours pas si l'API websocket gère les threads par elle même. Dans le cas contraire, il sera nécessaire de mettre en place un système de multithreading. Pour le moment, les sockets sont disposés sur deux threads. Un thread principal qui permet de recevoir les données du client (par exemple des données de l'air) et un thread secondaire, connecté aux changefeeds de rethinkdb, qui permettent de pousser tout changement sur la table vers un curseur infini. Lors de chaque changement du changefeed, les données sont envoyées aux clients. Ils sont d'abord traités par un décodeur qui permet de parser le JSON reçu, composé d'un champ old_val et new_val. Afin de simplifier, nous ne renvoyons que le champ non vide. Dans le cas ou les deux sont remplis, nous renvoyons les deux champs afin de comparer l'ancienne et nouvelle valeur.
Semaine 7
- Le site web récupère désormais les données issues de l'API REST. Nous utilisons pour cela les xhtmlHTTPrequest. Cette connexion est pour l'instant effectuée en localhost en faisant tourner en paralèlle la base de données rethinkDB ainsi que l'API REST. 2 requêtes sont alors nécessaires pour récupérer tous les points de mesure présents dans la base de données :
- La première requête à l'adresse "http://localhost:8080/unwheeze/auth/clientToken" avec le header 'Authorization':'Basic -token-' pour récupérer une API key qui sera utilisée dans la requête suivante. - La deuxième requête à l'adresse "http://localhost:8080/unwheeze/airData/getAirCollection" avec le header 'X-Api-Key': -API key-.
Ces deux requêtes sont effectuées de manières synchrone car nous avons besoin que celles ci soient effectuées afin de pouvoir continuer le reste du processus. Mais nous pourrons l'améliorer en l'utilisant de manière asynchrone. De plus, pour effectuer des requêtes en local, nous avons remarqué que nous devions lancer le navigateur en désactivant les sécurité. Par exemple : chromium-browser --disable-web-security --user-data-dir sur ubuntu avec chromium.
- Nous utilisons désormais Highchart pour afficher des graphs sur notre site web. Ces graphs afficherons l'évolution de la pollution au cours du temps au niveau du point cliqué par l'utilisateur. Ces graphs devront donc être modifiés pour prendre en compte les différents points de mesure de pollution se trouvant aux alentours du point cliqué durant les dernières 24H par exemple. Ceci fera donc l'objet d'une nouvelle requête à l'API Rest pour récupérer l'ensemble des points de mesures à afficher sur les graphs lors d'un clic.
Le point délicat étant de pouvoir retrouver quel point de mesure a été cliqué par l'utilisateur et pouvoir envoyer une requête appropriée à l'API. Nous voulons également laisser à l'utilisateur le choix de l'étendue des points qu'il souhaite comparer ainsi que la durée temporel sur laquelle il souhaite voir l'évolution de la pollution. L'affichage des graphs nécessite un bon moment de documentation quant a l'utilisation de l'API de Highchart.
- Nous avons également implémenté une Heatmap sur la carte google map. Celle affichera en rouge les points avec le plus de pollution et en vert les zones les moins polluée et à privilégier par l'utilisateur.
Semaine 8
- Nous avons reçu notre capteur et avons commencé à l'utiliser grâce à un Arduino pour le tester. Nous avons bien réussi à récupèrer les valeurs et sommes donc passé à l'ESP32. Nous avons alors dû réaliser le programme qui attend de recevoir un caractère par bluetooth depuis le téléphone pour envoyer les valeurs du capteur de pollution sur le téléphone. Nous arrivons alors à nous connecter, et recevoir sur les 3 champs différents les valeurs de PM10 PM2.5 et PM01 comme le montre la vidéo suivante :
watch?v=XzDKDh4UMxE&feature=youtu.be Cependant, notre programme devra utiliser le pin SET du capteur de pollution pour le laisser en mode faible consommation d'énergie tant que nous ne l'utilisons pas.
- Nous avons également apporté des modifications au site web afin de faire des ajustements esthétiques et permettre d'afficher les graphiques selon l'intervalle de temps et la distance choisie par l'utilisateur.
- Enfin, nous avons pu contacter une personne s'occupant de l'analyse des données de pollution sur Lille qui nous a expliqué comment vérifier les valeurs obtenues sur notre capteur. En effet, 2 stations de mesures sont disponibles sur Lille. Une stations de à proximité du traffic : Boulevard de Leeds 59700 Lille à coté du Crown Plaza et une station bruit de fond à coté de l'école Lakanal à fives (Groupe Lakanal Campau - Rue du long Pot 59800 Lille Fives).
Les valeurs sont prises à hauteur d'homme pour simuler au mieux la pollution à laquelle un être humain peut être exposé en ville.
Nous devrons donc vérifier si notre capteurs ne sous estime pas la pollution en ville ou au contraire ne les surestime pas. En effet, pour l'instant, nous avons seulement pu vérifier superficiellement que les valeurs étaient correctes. Dans notre maison, les valeurs sont entre 0 et 8 pour chaque polluant alors que à coté du pot d'échappement d'une voiture, nous arrivons jusqu'à des valeurs de 127ug/m3. Lorsque notre projet sera plus avancé, nous ferons donc les mesures juste à coté de ces deux stations afin de vérifier la précision de nos mesures et de vérifier que notre capteur est bien précis en comparant les valeurs avec celles disponibles sur le site de l'ATMO : http://www.atmo-hdf.fr/acceder-aux-donnees/mesures-des-stations.html
- Nous avons implémentés la quasi totalité des fonctionnalités REST et mis en place le serveur websocket, utilisant les changefeeds de RethinkDb. Ainsi, à chaque ajout d'un document, ou suppression, de la base de donnée, chaque client connecté au serveur websocket est notifié par le biais d'un paquet contenant le document modifié.
L'application Android se connecte maintenant au capteur et permet de réaliser une mesure et de l'envoyer sur le serveur. Nous utilisons le framework Volley afin de réaliser les requêtes HTTP. Nous travaillons maintenant à mettre en place une connexion websocket sur le smartphone, tournant en tâche de fond et notifiant l'utilisateur lors de la réception d'un message, réalisant les actions nécessaires, telles que l'affiche sur la carte.
Semaine 9
- Maintenant que notre capteur de pollution fonctionne, nous avons commencé le pcb pour faire fonctionner celui ci sans breadboard. Cependant, nous n'avons pas trouvé de fichiers permettant de modéliser notre ESP32 ainsi que notre capteur de pollution sur altium. Nous avions tout d'abord trouvé des fichiers fonctionnant sur eagle pour l'ESP32 mais ceux du capteur de pollution n'était toujours pas disponibles. Nous avons donc décidé de redessiner le fichier schematic et pcb pour les deux composants.
- Nous avons également commencé à dessiner un premier modèle de coque qui encapsulera tous les composants de notre capteur sur Freecad. Cette coque devra contenir la batterie, le capteur, l'ESP32 et un interrupteur pour allumer et éteindre le capteur.
- La largeur du pcb devra donc être en adéquation avec la largeur de la coque afin que tous les composants restent bien fixés lors des déplacements de l'utilisateur.
- Le back-end est quasiment complété. Il ne manque qu'à le mettre sur le cloud. Pour cela, deux choix sont possibles après discussion avec nos enseignants : soit utiliser une plateforme tierce, soit utilisée une machine virtuelle fournie par Mr Redon. Il s'agira d'une décision à prendre par la suite, lorsque nous nous assurerons que l'API et le serveur websocket fonctionnent sans aucun soucis.
Nous avons également fini d'implémenter les méthodes retournant un tableau JSON des points les plus proches à un point passé en paramètre de l'URL.
- Nous avons complétés la connexion websocket sur l'application et commencés l'écriture du service android qui tournera en fond. Nous utiliserons un BroadcastReceiver afin de communiquer avec l'activité principale de l'application et afficher les valeurs reçues sur la carte.
Nous avons également beaucoup travaillés sur le design de l'application afin de faire en sorte que la compréhension du fonctionnement soit intuitive.
Semaine 10
- Nous avons modifié le programme de l'ESP32 afin que celui ci passe en lower consumption mode lorsqu'il n'a pas besoin de faire de mesures. Nous avons également pu vérifier l'efficacité de ce changement en mesurant à l'aide d'un ampèremètre le courant effectivement consommé. En effet, lorsque le capteur est en état de fonctionnement, nous avons mesuré une consommation de 60mA et lorsque celui ci est au repos, nous avons mesuré moins de 10mA. Ce qui représente un grand gain en terme de longévité pour notre batterie.
- Nous avons terminé le PCB pour notre capteur de pollution que nous devons désormais imprimé afin de pouvoir vérifier son bon fonctionnement ainsi que sa compatibilité avec la coque en plastique. Nous avons également dû inverser certains pins sur l'adaptateur du capteur de pollution car le set et le sleep était fixé sur le coté opposé du mini pcb fournit et rendait donc difficile la connexion sur notre carte. Nous avons donc pu réaliser cette inversion avec l'aide de Thierry car la fixation industrielle de ces pins les rendaient difficile à désouder sans risquer de casser notre composant.
Semaine 11
- Nous avons pu graver notre PCB. Celui ci a été testé : aucun court circuit n'a été constaté. Nous avons également sélectionné les résistances qui nous permettrons d'allumer les LEDs sans créer de surtension dans les LEDs. En effet, notre ESP32 transmet une tension de 3,3V. Les deux leds que nous utilisons sont la OVS0806 (jaune) qui selon la datasheet accepte au maximum 20mA pour une tension de 2.1V tandis que nous n'avions pas la datasheet pour la led sml31ovtt86p (rouge). Nous avons donc décidé de calculer la chute de tension induite par les 2 leds grâce à un multimètre. Cela nous permettait donc de remédier au manque de datasheet pour la led rouge et de vérifier celle de la led jaune. Nous avons alors trouvé que la led rouge induisait une chute de tension de 1,45V et la jaune : 1,63V.
Sachant que nous devions avoir un courant de 20mA au maximum dans les LEDs. Nous avons décidé d'assurer une marge de sécurité et avons donc fait nos calculs avec 12mA. Nous trouvons alors que nous avons besoin de résistances de 139 Ohm pour la led rouge et 154 Ohm pour la led jaune. Cependant, après quelques tests, la LED jaune nous semblait éclairer un peu fort. Nous avons donc augmenté la valeur des résistances et avons choisi d'utiliser des résistances de 270 Ohm qui nous donnaient entière satisfaction.
- Nous avons également terminé la réalisation de la coque sur freecad dont voici le dessin 3D :
- Nous avons également essayé d'imprimer notre coque. Cependant, l'impression n'a pas fonctionné. Nous avions déjà dû relancer l'impression au soir car l'imprimante 3D s'était arrêtée puis nous l'avons laissée tourner pendant la nuit et celle ci s'est arrêtée au bout de quelques couches. Nous relancerons donc l'impression la semaine prochaine sur une autre imprimante.
Semaine 12
- Nous nous sommes mis à souder les composants sur notre PCB et avons pu tester ce dernier pour vérifier qu'il fonctionne correctement. Nous arrivons à allumer les 2 leds rouge et jaune ainsi qu'à utiliser le capteur de pollution avec l'ESP32. Enfin, nous avons dû connecter la batterie sur la carte. Cependant, nous avons rencontré un problème car si nous connections le PCB à la batterie avec un simple connecteur microUSB, nous aurions dû utiliser le câble prévu à cet effet. Ceci aurait eu pour conséquence d'augmenter la longueur de la coque du capteur de près de 5 cm afin de faire passer le câble microUSB. Nous avons donc décidé d'ouvrir la batterie afin de souder directement les fils sur celle ci. L'autre extrémité des fils étant également soudée directement sur la carte, cela nous permet donc un gain de place considérable afin de miniaturiser notre capteur.
- Au niveau de l'impression de la coque en 3D, nous avons de nouveau eu beaucoup de problèmes. En effet, l'impression s'est arrêtée comme la semaine dernière et nous avons donc dû nous y prendre à 3 fois pour enfin obtenir notre objet en 3D. Celle ci correspond à nos attentes. Tous les éléments passent dans la coque et ne bougent presque pas ce qui permettra une meilleur expérience utilisateur. Cependant, nous avons souder l'ESP32 sur la carte au moyen d'un connecteur en barrette femelle afin de pouvoir l'enlever et le remettre sur notre PCB. Celui ci a donc augmenté la place prise par l'ESP32 et nous avons désormais quelques difficultés pour fermer la boite. Nous réimprimerons donc par nos propres moyen une coque pendant les vacances.
Explication fonctionnement et réalisation
Site web
Le site web a été réalisé en grande partie à l'aide de javascript et de l'API de google maps qui offre énormément de fonctionnalités de localisation et d'affichage géographique qui étaient très intéressantes pour notre projet. Nous utilisons également Semantic UI qui est un framework de design web au même titre que Bootstrap ainsi que Highchart pour l'affichage des graphiques. Les xhtmlHTTPrequest de javascript permettent de communiquer avec l'API REST de notre serveur ainsi que L'API de google maps tandis que les websockets nous permettent de mettre à jour en temps réel les nouvelles données de mesure de pollution. En effet, si on ajoute une donnée dans la base de donnée, on peut voir le point de mesure apparaître sur la carte immédiatement sans recharger la page.
Organisation des fichiers : ????????????
Voici le visuel que l'on obtient lorsque l'on se connecte sur le site web de notre projet. Celui ci permet de visualiser les données récupérées par toutes personnes possédant un capteur. Chaque mesure est symbolisée par un petit rond de couleur allant du vert au rouge suivant le taux de pollution trouvé par le capteur. Lors de l'arrivée d'un utilisateur sur le site, le navigateur va lui demander si il accepte de divulguer ses informations sur sa position géographique via une fenêtre en haut à gauche de l'écran. Si celui ci accepte, la carte zoomera alors sur sa position actuelle afin de pouvoir afficher les mesures de pollution effectuées autour de lui. Dans le cas contraire, nous avons décidé de faire démarrer la carte sur la ville de Lille. L'utilisateur pourra alors se déplacer librement sur la carte afin de trouver les informations sur les taux de pollution aux endroits qu'il recherche. La localisation de la personne (ou la localisation par défaut si l'utilisateur n'autorise pas la géolocalisation) est affichée en haut à droit de la page. L'utilisateur peut alors simplement cliquer sur cette information pour centrer la carte atour de sa position. L'utilisateur étant représenté par un marker rouge sur la carte.
Les endroits où une mesure a été effectuée sont affichés sur une heatmap qui nous donne sans cliquer une indication de la pollution que l'on trouve aux différents endroits de la ville. Pour cette heatmap, nous aurions pu utiliser la fonctionnalité offerte de base par google map. Cependant, après avoir implémenté celle ci, nous nous sommes rendu compte que la heatmap de googlemaps prenait en compte la densité des points. En d'autres termes, si nous réalisions 100 mesures d'un taux très faible de pollution en un même point, celui ci apparaîtrait en rouge sur la heatmap dû au fait que les valeurs de pollution mesurée en chaque point s'additionnent. Ce résultat n'étant absolument pas convenable par rapport à ce que nous souhaitons obtenir. Nous avons donc trouvé heatmap.js sur le web qui est une heatmap fonctionnant sous forme d'interpolation. La densité des points n'est donc plus prise en compte et seul le poids donné à chaque point permet de modifier la couleur d'apparence sur la carte. Heatmap.js étant compatible avec la carte offert par maps comme le montre la documentation citée en bas de wiki. Nous avons également ajouté 4 boutons en haut à droite de la page pour permettre à l'utilisateur de choisir le type de polluant avec lequel il souhaite que la heatmap soit mise à jour. Le bouton le plus à gauche représente la moyenne des 3 polluants (Il représente la heatmap affichée par défaut lors de l'arrivée de l'utilisateur sur le site). Les 3 autres boutons permettent de mettre à jour la heatmap en fonction d'un polluant en particulier. Le type de heatmap active est indiqué par la couleur d'un des 4 boutons qui devient alors plus foncé que les autres.
On peut également obtenir une visualisation graphique des mesures de polluant. Celle ci est disponible en cliquant sur un des marker de la heatmap. Une fenêtre s'ouvre alors au dessus du point pour indiquer l'adresse du point cliqué (celle ci est récupérée à l'aide d'une requête à l'API de google qui converti le point exprimé en latitude/longitude, en adresse réelle. Le graphique contient les évolutions au cours du temps des 3 polluants. L'abscisse représentant la date à laquelle la mesure a été effectuée et l'ordonnée représentant le taux de PM25, PM10 ou PM1 mesuré à cet instant en μg/m3. Une légende est également présente en haut à gauche du graphique afin d'expliquer à l'utilisateur quelle courbe correspond à quel polluant. Enfin, en dessous du graphique, on retrouve les informations relatives à la mesure effectuée en ce point précis de la carte. On peut alors trouver le taux de pollution sur chaque polluant ainsi que l'heure exacte de la mesure. De plus, pour faciliter l'expérience utilisateur, nous avons également implémenté une fonctionnalité qui n'oblige pas l'utilisateur à cliquer précisément sur un marker. En effet, si l'utilisateur clic simplement sur un point de la carte, la fenêtre correspondant au point le plus proche s'ouvrira. La difficulté de cette fonctionnalité était de permettre à l'utilisateur de se déplacer sur la carte sans déclencher l'ouverture de la fenêtre du point le plus proche. Un click représentant un mouseDown, suivant d'un mouseUp sans mouseMove entre les deux.
L'utilisateur peut également obtenir davantage d'informations autour de ce point de mesure. En effet, il lui suffit de cliquer sur le petit "+" en bas à gauche de la fenêtre du marker pour ouvrir un volet sur le côté droit de la page. Celui ci est composé de 3 graphiques représentant chaque polluant ainsi que de 2 curseurs permettant à l'utilisateur de personnaliser son analyse de l'évolution des polluants au cours du temps. Les graphiques permettent d'obtenir une meilleur précision sur les mesures car l'échelle des ordonnées sera alors adaptée à chaque polluant.
Les curseurs permettent à l'utilisateur de modifier l'intervalle de temps au cours duquel les données de pollution vont être prisent en compte dans l'affichage du graphique ainsi que l'intervalle de distance jouant sur cette affichage. L'utilisateur peut alors choisir le nombre d'heures durant lesquelles il souhaite que l'analyse soit réalisée (par pas de 1h allant de 1h à 24h puis par pas de 1 jour allant de 1 à 3 jours). L'utilisateur peut également sélectionner dans quel périmètre il souhaite prendre en compte les données relevées autour du point sélectionné. Ce périmètre est représenté par un cercle bleu qui s'affichage lorsque l'on maintient enfoncé le curseur de distance afin de mieux visualiser la modification en cours. Le périmètre autour du point sélectionné peut être modifié par pas de 100m de rayon allant de 0 à 3km.
On peut alors voir sur cette capture d'écran que le graphique est modifié en temps réel lorsque l'on actionne l'un des deux curseurs.
partie choix du meilleur chemin ?????????
Capteur de pollution
Pour faire fonctionner notre capteur de pollution tout en offrant à l'utilisateur une utilisation facilité et plus agréable, nous avons dû réaliser un PCB, une modélisation 3D de la coque entourant ce capteur ainsi que le programme a intégrer dans l'ESP32 afin de faire fonctionner tous les éléments ensemble. Nous allons donc vous décrire ces éléments un par un.
La carte éléctronique
Pour réaliser notre carte électronique, nous avons beaucoup hésité sur le choix du logiciel que nous allions utiliser afin de nous faciliter la tâche. Cependant, nous n'avons pu trouver les footprints de nos composants sur aucun logiciel et avons donc décidé d'utiliser Altium car nous avions déjà eu un cours sur la réalisation des PCB avec ce logiciel.
Le premier travail fut donc de réaliser les footprints et schematic de chacun de nos composants. Le plus long fut de prendre en main le logiciel et comprendre comment réaliser au mieux ces fichiers. L'empreinte de l'ESP32 ne fut pas très compliquée. Il a suffit de fixer la grille à 1,27mm afin de pouvoir poser chaque pastille espacée de 2.54mm. Notre ESP32 étant composé de 20 pastilles de chaque coté.
Pour l'adaptateur du capteur de pollution, cela fut un peu plus complexe car nous ne possédions pas de datasheet fiable. La datasheet portait à chaque fois sur le capteur en lui même et non pas sur l'adaptateur. L'adaptateur du capteur est composé de 6 pins espacés de 2.54mm ainsi que de 2 pins représentant le reset et le set qui, eux, furent difficile à positionner. En effet, nous avons dû mesurer à l'aide d'un pied à coulisse (pour plus de précision) les espacements entre ces deux pins et le reste des pins de l'adaptateur afin de réaliser la footprint.
De plus, les pins de set et reset étaient positionnés dans le sens opposé au reste des pins comme le montre la photo sur la gauche. Ce positionnement ne nous arrangeait pas pour le fixer sur notre PCB. Nous avons donc décidé d'inverser les pins pour nous faciliter la tâche.
Nous avons également dû faire attention à la largeur des pastilles sur nos footprints. En effet, nous avons dû recommencer notre carte car les trous n'étaient pas assez large. En mesurant au pied à coulisse, nous avons pu vérifier que nos pins étaient de forme carré de 0.7mm de côté. Cela nous obligeait donc à utiliser des pastilles de 1mm de diamètre. Enfin, pour interrupteur, nous avons dû utiliser des pastilles CMS qui se positionnent de la même façon que les précédentes. mais en modifiant par la suite la configuration de cette dernière.
Le visuel des footprints réalisées est visible ci dessous et les fichiers des footprints et schematics sont téléchargeables en cliquant sur le lien ci après pour une future utilisation sur altium : footprints et schematics
Nous avons ensuite réalisé le schéma composé de tous nos composants afin de les relier entre eux et de pouvoir créer les chemins qui apparaitrons sur la carte : Enfin, nous avons ajouté le plan de masse ainsi que les contours mechanicals :
Pour alimenter notre carte, nous avons décidé de connecter 2 fils directement sur la batterie afin de pouvoir miniaturiser notre capteur. Cette astuce nous permettant de gagner 4 à 5 cm de longueur sur le capteur car nous n'avons plus besoin de câble pour connecter notre capteur. Ces deux fils ont été soudés sur la carte au moyen de pins car nous avons utilisé un fil épais pour transporter le courant jusqu'à la carte. Un interrupteur permet par la suite de séparer le reste de la carte de la batterie. En effet, cela nous permet de pouvoir téléverser un nouveau programme dans l'ESP32 facilement sans risquer de poser problème entre l'alimentation par la batterie et le câble usb du PC. Nous avons également positionner des headers sur la carte afin de ne pas souder directement l'ESP32 et l'adaptateur du capteur de pollution sur le PCB. Cependant, les pins utilisés sur l'ESP32 étant assez gros, il n'est pas facile de le retirer. Notre interrupteur nous permet donc de téléverser nos programmes sans risque d'endommager les pins de l'ESP32 en le retirant.
La coque
Les principaux objectifs de notre capteur étaient qu'il soit fonctionnel, facilement transportable et donc le plus petit possible. Enfin, il fallait que les différents composants soient bien fixés pour ne pas bouger à l'intérieur de la coque et enfin, pouvoir protéger le capteur du vent qui peut affecter sa précision.
Nous avons donc tout d'abord dessiné des schémas à la main représentant le capteur que nous souhaitions avec les dimensions de celui ci. Nous avons hésité entre un capteur de forme ronde ou rectangulaire mais nous nous sommes finalement décidé pour une forme rectangulaire car le gain de place est plus important. Nous avons donc simplement arrondi les bords afin d'améliorer un peu le design de l'objet. Voici les schéma que nous avons dessinés :
§§§§§§§§§§§§§§§§§§§§§§§§§ SCHEMA §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
Vous pouvez donc voir sur le schéma numéro 1 qu'une chambre d'air a été créée autour du capteur de pollution. Les trous dans les parois de tous les cotés permettent de laisser passer l'air à analyser tout en évitant d'avoir des trop grands afflux d'air qui peuvent perturber le capteur. De plus, le capteur est maintenu en position de chaque coté par des petits supports de plastique. Un petit support le maintient également en hauteur pour que le capteur soit bien au centre de la chambre d'air. Enfin, un trou a été laissé sur le coté afin de laisser passer les câbles du capteur jusqu'au PCB.
La batterie est, elle, maintenue des deux cotés afin de ne pas bouger et des trous ont été dessinés afin de pouvoir : appuyer sur le bouton marche/arrêt et de pouvoir brancher le câble de rechargement de la batterie.
Un espace a également été prévu pour venir placer le PCB au dessus de la batterie. Celui ci sera alors maintenu par une petite partie en plastique qui ressort de chaque coté. La partie supérieure de la coque est également perforée pour laisser passer l'air et permettre de voir les LEDs qui s'éclaireront pour dire si le capteur est allumé et si il est en train de prendre une mesure. Cette partie supérieure de la coque vient ensuite se refermer sur le PCB est le bloque totalement afin que celui ci ne bouge plus. Tous les éléments sont donc bien maintenus dans la coque.
La deuxième étape été donc la réalisation des précédentes esquisses sur un logiciel de CAO. Comme nous avions déjà utilisé Freecad l'année dernière et que ce logiciel est libre et gratuit, nous nous sommes penchés vers cette solution. Le résultat obtenu est alors très proche de ce que nous avions décidé et nous permet d'avoir un capteur pratique et facilement transportable comme nous l'espérions :
Nous avons donc pu l'imprimer sur les imprimantes 3D disponibles à l'école en utilisant le logiciel Cura et nous avons utilisé du support lors de l'impression afin d'être sur que toutes les parties soient bien réalisées correctement. En effet, les rebords pour poser le PCB par exemple, se trouvent sans aucune matière plastique en dessous et nécessite donc un support. En sortie d'imprimante, nous avons donc obtenu les pièces suivantes auxquelles nous avons dû retirer le support resté attaché en fin d'impression :
Cependant, nous avons dû réaliser une deuxième coque plus haute que la précédente car nous avons finalement décidé d'utiliser des headers plutôt que de souder directement notre ESP32. Ceci a entraîné une augmentation de la place prise par ce composant. Cependant, lorsque nous avons voulu réimprimer cette pièce, nous avons subit 3 échecs d'impression sur les imprimantes de l'école. Nous avons alors reçu l'aide de Erwan qui nous a permis d'imprimer pendant les vacances le bas de notre coque sur son imprimante personnelle et donc de pouvoir terminer celle-ci.
Le programme ESP32
Le programme intégré dans l'ESP32 a été réalisé au moyen du logiciel Arduino. En effet, celui ci nous permettait d'utiliser toutes les fonctionnalités dont nous avions besoin. Le programme nous permet donc de créer l'appareil ainsi que le serveur BLE. Celui ci signale donc la présence de notre ESP32 comme étant un appareil bluetooth auquel on peut s'appairer. De plus, une fonction de callback permet de recevoir un caractère depuis le téléphone via bluetooth. Pour faire la communication, nous avons choisi d'envoyer le caractère arbitraire "B" pour demander à l'ESP32 d'effectuer une mesure.
Lors de notre programme principal, nous attendons qu'un téléphone se connecte à l'ESP32. Si cela se produit, on va utiliser une boucle while pour vérifier toutes les 100ms si notre ESP32 reçoit le caractère "B" dans la variable rxValue. Dans le cas contraire, nous remettons l'ESP32 en mode sleep afin de consommer moins d'énergie. De plus, nous utilisons un signal sur le pin 5 de l'ESP32 permettant également de mettre le capteur de pollution en mode sleep. Nous le mettons donc à l'état bas lorsqu'aucune mesure n'est demandée puis nous passons le signal à l'état haut avant de demander une mesure. Cependant, nous avons remarqué que si nous nous laissions pas un delay entre le moment où nous sortons le capteur de pollution du mode sleep et le moment où nous effectuons la mesure, celles ci étaient fausses. Nous avons donc décidé d'imposer un delay de 5 secondes avant de prendre la mesure. Ce temps d'attente nous parrait acceptable au vu du gain sur l'autonomie de la batterie.
Lorsque le caractère "B" est reçu, on va alors rechercher la mesure prise par le capteur. Les mesures sont envoyées par liaison série suivant le protocole suivant : Baudrate: 9600, Parité: None; Stop Bits: 1; longueur du paquet : 32 octets.
nom |
Start char 1 | Start char 2 | length | data 1 | data 2 | data 3 | data 4 | data 5 | data 6 | data 7 | data 8 | data 9 | data 10 | data 11 | data 12 | data 13 | check data sum |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Nombre d'octets |
1 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
signification |
0x42 | 0x4d | 2*9+2 | concentration of PM1.0, ug/m3 | concentration of PM2.5, ug/m3 | concentration of PM10.0, ug/m3 | test data interne | test data interne | test data interne | nombre de particules de diamètre supérieur à 0.3um pour 0.1 litre d'air | nombre de particules de diamètre supérieur à 0.5um pour 0.1 litre d'air | nombre de particules de diamètre supérieur à 1.0um pour 0.1 litre d'air | nombre de particules de diamètre supérieur à 2.5um pour 0.1 litre d'air | nombre de particules de diamètre supérieur à 5.0um pour 0.1 litre d'air | nombre de particules de diamètre supérieur à 10.0um pour 0.1 litre d'air | test data interne | somme de tous les octets précédents |
Pour vérifier qu'une mesure a été prise, on va regarder lorsque l'on reçoit le caractère 0x42 sur la liaison série. Cela signifie alors que les 31 bits qui suivent sur la liaison série représentent la trame. Celle ci est donc enregistrée dans notre variable buf qui est un tableau de char de longueur 31 pour contenir tout le reste de la trame. Nous analysons ensuite celle-ci afin de vérifier que les octets reçus représentent bien le message envoyé par le capteur et qu'aucune erreur n'a été introduite durant la transmission. Nous vérifions donc que le premier octet de la trame est bien l'octet 0x4d puis nous vérifions que le checksum final est bien égal à la somme de tous les octets de la trame. Enfin, après nous être assuré que la trame est correcte grâce aux vérifications précédentes, nous récupérons les octets 5 et 6 pour le PM1, 7 et 8 pour le PM2.5 et les octets 9 et 10 pour le PM10. Ces valeurs, une fois récupérées doivent être converties en string afin de pouvoir les envoyer au téléphone qui se chargera de les enregistrer et de les afficher à l'utilisateur.
Le backend
API REST
L'API REST à été réalisée entièrement en Java, comme annoncé dans l'analyse de pré-projet. Nous avons utilisé le framework Jersey, intégré à JEE, qui offre de nombreuses simplifications, avec notamment l'utilisation des annotations, qui remplacent l'héritage de classes afin d'implémenter des comportements face aux requêtes.
L'API REST est organisée en trois différents classes de requêtes, dont deux se révèlent particulièrement importantes pour notre projet, tandis que la dernière classe de requête, associée aux actions utilisateurs, n'est pas vraiment nécessaire au fonctionnement du projet. Nous expliquerons par la suite le contenu de ces différentes classes de requêtes, avant de passer à une description plus approfondie des méthodes employées à la réalisation.
Notre choix de la base de données à utiliser sur ce projet s'est portée sur RethinkDb, pour trois raisons principales :
- Le caractère open-source du projet, qui est maintenu par la communauté.
- Le type de cette base de donnée, de type NoSQL, qui est plus adapté à notre projet au vue des fréquentes modifications que nous réalisons sur les données stockées
- La présence d'un coté temps réel, par la fonctionnalité "d'abonnement" à une table, ce qui renvoi en temps réel les modifications effectués.
RethinkDb dispose d'un GUI très pratique permettant de gérer toutes nos bases de données soit par ligne de commande directement sur le GUI, soit en utilisant les outils présents sur la page web. En plus de cela, RethinkDb dispose de toutes les fonctionnalités présentes sur des bases de données plus connues, telles que MongoDb, à savoir, les pipelines, l'indexing, la gestion des données de géolocalisation, qui se révèle très pratique dans notre cas, car cela nous permet de ne pas nous occuper des calculs tels que la détermination de distance entre deux points, qui est directement réalisé par la fonction getNearest() de RethinkDb.
L'une des deux premières classes de requêtes correspond aux requêtes de sécurité, qui permettent d'obtenir des clés d'API, ou un token utilisateur afin de réaliser des actions nécessitants des privilèges. Ces méthodes d'obtention de clés sont primordiales : aucune requête ne peut être réalisée sans la spécification des clés obtenus dans un header. La clé d'API permet de réaliser les requêtes correspondant à la classe des requêtes des données de l'air. Il n'est pas nécessaire d'être authentifié pour l'obtenir. Le tableau suivant décrit les requêtes possibles de cette classe.
URL | Méthode | X-Api-Key | Consomme | Produit | Commentaire |
---|---|---|---|---|---|
/auth/clientToken | GET | Non | Aucun | JSON | Retourne un objet JSON avec un champ key
contenant la clé. |
/auth/token | GET | Non | Aucun | JSON | Retourne un Json Web Token (JWT) à l'utilisateur.
Le header doit contenir un champ Authorization contenant son email et son mot de passe de la forme email:mdp encodé en base 64. Le JWT est valide uniquement pour une durée limitée. |
Le tableau suivant regroupe la liste des requêtes possibles de la classe des données de l'air. Cette classe de requêtes permet d'insérer une donnée de l'air à travers une requête POST, dont les spécifications sont précisées par la suite. Elle permet, à travers plusieurs requêtes GET de récupérer une donnée de l'air spécifique, l'ensemble des données ou encore, les données les plus proches d'un point particulier.
URL | Méthode | X-Api-Key | Consomme | Produit | Commentaires |
---|---|---|---|---|---|
/airData/putAirData | POST | Oui | JSON | JSON | Consommes un élément suivant le modèle
de l'objet AirData, décrit par la suite. |
/airData/getAirCollection/ | GET | Oui | Aucun | JSON | Renvoi un tableau JSON de tout les points mesurés
présents dans la base de donnée. |
/airData/getAirData/{id} | GET | Oui | Aucun | JSON | Retourne un point mesuré en particulier, spécifié dans
l'URL par son UUID. |
/airData/getNearest/{location} | GET | Oui | Aucun | JSON | Retourne un tableau JSON contenant
la liste des points les plus proches du point specifié selon le format latitude,longitude dans l'URL. L'objet retourné dispose de la distance dans un champ dist et du point en question dans le champ doc. |
L'ensemble des requêtes, comme indiqué dans le tableau, nécessitent la présence d'une clé d'API dans le header X-Api-Key. Une clé invalide renvoi un code 403 (accès refusé). La spécification du header content-type est également nécessaire dans le cas de la requête d'insertion. Les requêtes consomment du JSON, il faudra donc spécifier application/json.
Enfin, une donnée insérée doit contenir nécessairement les champs suivants :
{ "location":"104.28,32.25", "pm25":254.5, "pm10":500, "pm1":250, "geolocation": POINT(104.25,32.25), "datetime":"2018-04-02T22:55:58.545Z" }
L'id est généré automatiquement. Le champ geolocation contient un élement JSON de type Point défini par RethinkDb. Un java bean de cet objet JSON est disponible sous la package bean du code source de notre API, défini par la classe GeoBean. Il n'est normalement pas nécessaire de se soucier des champs geolocation et datetime, l'API les ajoutants automatiquement.
Ce format d'insertion correspond également au JSON renvoyé lors des requêtes GET, à la seule différence que le champ ID est également retourné.
Serveur websocket
Nous avons mis en place un serveur websocket afin de maintenir une communication bilatérale entre le serveur et les clients. Nous prenons avantage de la fonctionnalité "d'abonnement" à une table, décrite précédemment, afin d'implémenter le caractère temps réel de l'application. Ainsi, à l'ouverture de la connexion websocket, un nouveau thread est lancé afin de traiter de manière asynchrone les demandes d'abonnement à la table contenant les données relatives à l'air. Ainsi, à chaque insertion ou modification d'une donnée, un message est envoyé à tout les clients abonnés, contenant le nouvel objet ajouté, selon la syntaxe décrite dans la partie précédente. A la réception d'un message, le serveur insère la donnée dans la base de donnée.
L'URL d'accès au serveur websocket est :
ws://18.219.202.43:8080/Unwheeze/realtime/airDataFlow
Le fonctionnement interne du websocket est très simple, notamment grâce à l'implémentation native des websockets sous Jersey. Il est simplement nécessaire de spécifier l'annotation @ServerEndpoint, ainsi que les encodeurs et les décodeurs, qui eux permettent de formater les messages entrants ainsi que les messages sortants.
L'encodeur est mis en place en implémentant l'interface Encoder.Text qui fournit une méthode encode prenant en paramètre un bean représentant le format du message sortant et renvoyant une chaine de caractère le définissant. Le décodeur est implémenté de la même manière sinon que la méthode décode prend en paramètre une chaine de caractère et renvoi un objet java bean qui le représente.
Déploiement sur Amazon Web Service
Afin de déployer notre serveur Tomcat, exécutant notre API REST, nous avions le choix entre utiliser une machine virtuelle fournie par Mr. Redon ou d'opter pour une solution de notre choix. Nous avons fini par opter pour un déploiement sur Amazon Web Service (AWS) en raison du fait que la machine virtuelle n'était pas assez puissante afin de faire tourner RethinkDb. Amazon Web Service, de par son service EC2, offre la possibilité de lancer des instances linux, sous les distributions de notre choix. Les instances sont connectés aux serveurs Amazon et disposent donc d'un accès internet. Nous avons du configurer une adresse IP et ouvrir les ports afin d'accéder à notre serveur Tomcat. Cette configuration se fait par le biais de l'interface proposée par AWS. Afin d'ouvrir les ports aux paquets entrants, nous avons du mettre en place un groupe de sécurité, dans lequel nous définissions une autorisation à tout les paquets HTTP entrants sur les ports 80 et 8080.
L'adresse IP associée à notre serveur Tomcat est : http://18.219.202.43:8080/Unwheeze/
L'application mobile
Nous avons décidé de porter une attention particulière à la réalisation de l'application mobile: afin de refléter au mieux l'importance du projet, il était nécessaire de nous conformer également aux codes de design des applications actuellement disponibles réalisant plus ou moins le même but. Ainsi, nous avons passé un temps conséquent sur la réalisation du design de l'application, qui, bien que sobre, refléte les normes dictées par Google afin de se conformer à son Material Design, tout en se permettant quelques libertés particulières.
Ainsi, la couleur principale choisie refléte l'environnement, sachant que notre projet porte essentiellement sur ce sujet. La couleur secondaire est le bleu, correspondant au ciel, notre projet portant sur la qualité de l'air.
L'application à été conçue pour être la plus simple d'utilisation possible, elle se divise en trois parties principales :
- La page de chargement, plus communément appelée Splash screen
- L'activité principale, qui réalise la fonction principale du projet
- Les activités et fragments secondaires, qui permettent d'afficher des détails ou de tracer des graphiques.
La page de chargement est inspirée des lignes de conduites google, qui recommandent d'effectuer le chargement principal, souvent lourd et imposant une latence à l'ouverture de l'application, dans un thread secondaire, tandis que le thread principal affiche une interface plus plaisante à regarder qu'une interface blanche et vide. Le thread de chargement contacte l'API REST par une requête GET, afin d'obtenir une clé API et la stocker dans un fichier de données privé et propre à l'application. Nous vérifions également la présence du bluetooth ainsi que des services de localisation. La présence de ce dernier est primordiale, car nous chargeons la localisation dans le même fichier de données que précédemment afin d'afficher la carte centrée sur la localisation de l'utilisateur, mais également pour télécharger uniquement les données relative à la ville actuelle.
L'activité principale affiche la carte ainsi qu'une heatMap agrémentée de marqueurs représentants les données mesurées par les différents capteurs. Le bouton présent en bas à droite déploie un sous menu permettant de connecter le capteur : si le bluetooth et la localisation ne sont pas activés, il est demandé à l'utilisateur de les activer. Une fois la connexion réalisée, le bouton change de couleur et prend la couleur bleu de bluetooth. Un second clic est nécessaire afin de déconnecter le capteur. Une fois le capteur connecté, nous pouvons réaliser une mesure avec le bouton du dessus. Une fois les données reçues, un fragment s'affiche en bas de l'écran avec les données mesurées et un smiley représentant la qualité globale de l'air. Une option est disponible afin d'obtenir le graphique correspondant aux mesures environnantes et sur un temps prédéfini. Enfin, la carte est mise à jour à chaque réception d'information via la connexion websocket, qui est lancée via un service tournant en fond. Une réception par ce service lance une méthode dans l'activité principale permettant d'insérer la donnée dans la base de donnée et de recharger la carte. Ce service tourne uniquement pendant la durée de vie de l'activité principale, afin de ne pas impacter les performance d'un utilisateur disposant d'un dispositif android bas de gamme.
L'activité secondaire permet d'observer les graphiques représentants les données disponibles. Ces graphiques peuvent être configurés sur le temps ou sur l'espace, de la même façon que sur le site web. En effet, nous désirions reproduire fidèlement les fonctionnalités du site web sur l'application mobile, sachant que certains utilisateurs préfèrent l'un ou l'autre. Nous avons choisi la librairie MPAndroidChart afin de tracer nos graphiques, car libre et open-source, et réalisant le travail assez fidèlement. La base de donnée utilisée est la base de donnée intégrée par la librairie de base Android, SQLite.
Nous utilisons intensivement le multi-threading afin de permettre à l'utilisateur de ne pas être impacté par les divers chargements. Ce multi-threading s'observe et se montre très utile majoritairement dans la manière dont nous gérons les requêtes HTTP. En effet, la documentation Android recommande très fortement d'utilisé la librairie Volley, maintenue par Google, afin de réaliser toute action relative aux requêtes. L'un des avantages majeurs de cette solution est qu'elle permet un caching des données reçues : certes, la mémoire utilisée sera plus élevée. Cependant, dans le cas de plusieurs requêtes d'affilés, sans changement entre celles-ci, nous n'aurons pas besoin de solliciter la connectivité de l'utilisateur, et stockerons moins de valeurs en mémoire. Nous retrouvons également un très grand avantage dans l'utilisation de l'observer pattern dans la gestion des réponses en cas de succès où d'erreurs: les requêtes sont ainsi asynchrones et n'impactent pas l'utilisateur, car indépendants de la latence du serveur ou de la vitesse de connexion.
L'application utilise une connection Bluetooth Low Energy (BLE) afin de pouvoir profiter de la possibilité d'utiliser BLE sur l'esp32, permettant de réaliser d'importantes économies d'énergie sur les deux appareils. BLE sur smarpthone android nécessite l'activation du bluetooth mais également des services de localisation. Nous nous sommes demandés en quoi la localisation pouvait influer sur une liaison bluetooth : les différents forums (StackOverFlow) et plusieurs sites web tendent vers différentes réponses, à savoir, que l'activation des services de localisation constitue simplement un moyen d'informer l'utilisateur que l'utilisation du BLE autoriserait l'appareil connecté à recevoir des informations sensibles sur le smartphone (MAC par exemple), ou encore, qu'il s'agit simplement d'un bug qu'Android devrait régler dans ses versions futures.
Enfin, nous avons tentés de régler toutes les erreurs possibles qui pouvaient amener l'application à se terminer, où encore, qui entravaient à une bonne utilisation des services par l'utilisateur : des messages d'erreur sont ainsi affichés lors d'une action non autorisée et des messages de warning indiquent les fonctionnalités de l'application qui seront implémentés dans le futur (car non nécessaire au but principal du projet). A ce jour, tout les bugs connus ont été réglés, cependant, il s'agit d'un travail en continu et nous ne pourrons détecter de prochains bugs qu'à travers le test de notre application sur plusieurs appareils et dans plusieurs situations différentes.
Analyse des performances de l'application
Android Studio fournit un utilitaire d'analyse des performances en temps-réel, que nous avons trouvés pas très intelligent de ne pas nous en servir. En effet, l'un des majeurs casse-têtes qui intervient dans le développement d'une solution logicielle sur un objet connecté (bien qu'un smartphone actuel ne soit pas très concerné), est d'utiliser le moins de ressources possibles et d'éviter les taches de fond lorsqu'elles ne sont pas absolument nécessaires.
Ainsi, le lancement de l'application montre une utilisation relativement élevée du CPU et des fonctions réseau, ce qui s'explique par le fait que nous réalisons une requête chargeant l'ensemble des données contenues sur notre serveur, dans une base de données interne au smartphone SQLite, dans la perspective de diminuer le nombre de requêtes par la suite et le temps de chargement. L'utilisation élevée du CPU est normale et est dû au fait que nous créons l'interface de l'application en sollicitant une grande partie des ressources libres du smartphone.
Nous réalisons une nouvelle acquisition, cette fois-ci durant la connexion du smartphone au capteur par bluetooth LE: les avantages de l'utilisation du bluetooth faible energie se confirment car l'utilisation du CPU est très faible.
Enfin, une dernière acquisition est réalisée, cette fois-ci, lors de l'envoi d'une demande de mesure au capteur, et la réception de celle-ci, donc l'envoi au serveur et la nouvelle réception d'un paquet websocket contenant ces nouvelles valeurs. Nous observons clairement une activité sur le CPU et réseau, mais rien qui se trouve anormalement élevé.
Mesures, Interprétation et validation de notre prototype de capteur
Mesure expérimentale à l'aide de notre capteur
Mesure théorique relevées par l'agence ATMO
Documents Rendus
Documentation
heatmap.js pour gmaps : https://www.patrick-wied.at/static/heatmapjs/example-heatmap-googlemaps.html