1. Introduction

Dans la vie de tous les jours, il peut être difficile de se rappeler de tout ce que nous voulons ou devons faire. Pour remédier à cela, chacun a sa technique, comme par exemple associer une certaine information à une autre, pour que l'une rappelle l'autre. Pour ma part, j'ai pris l'habitude de faire des listes sur papier. Je le fais même souvent, si bien que de nombreuses listes remplissent ma chambre. Pour éviter ce désordre et ce gaspillage de papier, je vais faire une liste de choses à faire ("To-Do List") centralisée et en ligne que je pourrais afficher et actualiser depuis n'importe où.

Ce projet implique de travailler pour la première fois avec des bases de données ainsi que les différents langages de description et de programmation du Web. L'idée que j'ai de ma To-Do List ne se concrétisera donc peut-être pas entièrement mais je pense pouvoir mener le projet jusqu'à un niveau satisfaisant.

Le but de ce projet est d'afficher sur un écran tactile dans ma chambre une liste de choses à faire. Cette liste sera stockée sur une base de données sur un serveur et je pourrai y accéder à travers une page web stockée sur ce même serveur. Je pourrai donc y accéder depuis l'écran tactile dans ma chambre mais également depuis n'importe quel navigateur internet. Chaque tâche pourra être validée depuis cette même page afin qu'elle ne soit plus affichée. Cette liste sera également modifiable et configurable depuis une autre page web pour qu'il soit possible d'ajouter de nouvelle tâches sans avoir à accéder à la base de données en elle-même. L'idée étant que je puisse depuis un ordinateur ou même mon smartphone ajouter des tâches à faire dans la matinée quand je suis au gymnase et que quand je retourne dans ma chambre dans l'après-midi, celles-ci soient visible sur l'écran tactile.

2. Matériel et méthodes

2.1 Matériel

  • 1 x Raspberry Pi 2 ou modèle équivalent
  • 1 x écran tactile utilisable avec le Raspberry Pi
  • 1 x câble Ethernet
  • 1 x câble USB à micro-USB et adaptateur secteur si nécessaire
  • 1 x ordinateur
  • 1 x serveur web avec MySQL installé

La majorité du matériel nécessaire est disponible dans le cadre de l'option complémentaire d'informatique du gymnase de Renens, site Provence. Un câble Ethernet, pour l'accès à Internet, et USB à micro-USB, pour faire fonctionner l'appareil, sont tout de même nécessaires pour faire fonctionner la "To-Do List" sur l'écran tactile connecté au Raspberry Pi étant donné que celui-ci ne dispose pas de connectivité Wi-Fi et pas de batterie intégrée. Avec le nouveau modèle 3, qui lui dispose d'une interface Wi-Fi (voir https://www.raspberrypi.org/product...), et l'ajout d'une batterie externe portable, il serait donc possible de rendre ce projet entièrement portable et bien plus pratique car on pourrait le transporter avec nous au fur et à mesure que les tâches sont effectuées.

2.2 Méthode

Le code source du projet est disponible ici : https://dev.gyre.ch/git?p=gyreoci-1617.git;a=tree;f=Source;h=caf388508de5c640976be1d4f00dc537982166fd;hb=HEAD

2.2.1 Afficher la liste des tâches

Avant de pouvoir l'afficher, il faut créer notre base de données sur le serveur web. Celui-ci était déjà configuré et il a suffit de se connecter avec PHPMyAdmin, une interface graphique pour accéder aux différentes bases de données. Sur la base de données "kilian.deternod", on crée une liste appelée "ListeTaches" qui contient cinq champs. Le premier est un identifiant "taskID", une clé unique qui s'auto-incrémente à chaque fois qu'une nouvelle tâche est crée, qui permet de retrouver une tâche très facilement. Le deuxième, le troisième et le quatrième sont, respectivement, le nom de la tâche, la date limite à laquelle celle-ci peut être effectuée et sa priorité (qui va de "1" peu important à "3" très important). Le dernier champ "achieved" est vide ("NULL") par défaut et ne peut prendre que deux valeurs : "TRUE" lorsque la tâche a été correctement effectuée et "FALSE" lorsque celle-ci n'a pas été faite dans les temps. Il est important que le bon type de champ soit choisi selon le type de données (numériques, textuelles ou booléennes par exemple) non seulement pour éviter de gaspiller de la place mais aussi pour rendre la gestion de la base de donnée plus efficace.

Une page web est ensuite nécessaire pour afficher la liste des tâches ("show_list.php"). Il semblait clair depuis le début que la meilleure façon de l'afficher serait dans un tableau, ce qui a donc été fait en HTML avec une "table". Quatre champs sont nécessaire : un pour la priorité, un pour le nom de la tâche, un pour sa date limite, et finalement un qui permette de valider la tâche.

On récupère ensuite les données disponible sur la base de données du serveur avec du PHP. Pour cela, le module MySQLi est utilisé avec de la programmation orientée objet, ce qui a été un peu difficile à comprendre au début mais est devenu très utile. D'abord, on se connecte à notre base de données (ici "kilian.deternod" sur "localhost", donc le serveur sur lequel la page web est stockée, avec nos identifiants) et on envoie une requête pour demander dix tâches dont la valeur "achieved" est encore vide, donc qui sont encore en suspens, en commençant par celle dont les dates sont les plus petites, donc les plus proches d'aujourd'hui, et ensuite selon leur priorité, de la plus urgente à la moins urgente. On utilise ensuite une boucle pour assigner les valeurs des champs de la base de données qui sont associées entre elles (donc qui appartiennent à la même ligne) en utilisant "fetch_assoc()". Une ligne à la fois, on utilise ces valeurs dans le tableau. La valeur de priorité est utilisée pour créer trois classes (de l'attribut classe) qui seront utilisée plus tard en CSS dans les cellules concernées. On affiche le nom puis la date, dans un format agréable à lire. Finalement, on crée un "input" de type "submit" dans un formulaire, un bouton donc, qui sera utilisé pour valider une tâche. On nomme à chaque fois le bouton avec l'identifiant de la tâche à faire et on lui attribue la valeur "Valider", ce qui sera utile plus tard pour savoir sur quel bouton l'utilisateur de la page aura cliqué lorsqu'il veut valider une tâche. Il est important après cela de fermer la connexion que nous avons ouvert avec la base de données pour ne pas créer de multiples connexions qui pourraient surcharger le serveur. On va réutiliser cette même configuration pour afficher notre liste dans la deuxième page ("edit_list.php" qui deviendra plus tard "index.php" pour qu'elle s'affiche par défaut lorsqu'on accède à notre répertoire sur le serveur) qui sert à modifier notre liste avec la seule différence que les boutons auront comme valeur "Supprimer" et non pas "Valider".

2.2.2 Valider ou supprimer des tâches

Pour chaque tâche, il y a un bouton qui permet de la valider mais pour l'instant celui-ci ne fait rien. Comme vu plus tôt, à chaque bouton est attribué une variable dont le nom est l'identifiant de la tâche à laquelle il appartient et dont la valeur est "Valider", c'est cette variable là que l'on va utiliser pour traiter la tâche. On envoie donc cette variable à une autre page qui est "button_form.php" avec la méthode POST, ce qui signifie qu'elle ne passe pas par l'URL pour éviter de mauvaises manipulations, volontaires ou involontaires. Sur cette nouvelle page web, on va relancer une nouvelle connexion avec la base de données et on va vérifier si la variable du bouton que nous avons reçu existe, pour être sûr, puis si elle correspond à l'identifiant d'une des tâches de la base de donnée en utilisant presque la même configuration que pour afficher la liste et en testant chacune des lignes. Si l'on détecte une ligne où l'identifiant correspond à la variable que nous avons reçu du bouton et que la valeur de notre variable est "Valider", on va alors assigner la valeur "TRUE" ou 1 au champ "achieved". Ce qui veut dire que la tâche que nous avons validé avec le bouton sur la page précédente a été validée dans la base de donnée ne sera plus affichée. On utilise le même système dans la deuxième page "index.php". On est également redirigé vers cette même page mais la valeur de la variable envoyée par le bouton est "Supprimer" et non pas "Valider". Si l'on détecte donc une ligne où l'identifiant correspond à la variable mais que la valeur est "Supprimer", on supprime directement la ligne qui correspond à l'identifiant dans la base de données. Si on ne détecte aucun identifiant correspondant à une tâche dans la base de donnée, c'est qu'une erreur est forcément apparue quelque part. Dans ce cas, on imprime l'erreur. On utilise également une balise "meta" qui va servir à relancer l'utilisateur sur une autre page, ici le "HTTP_REFERER" c'est à dire la page d'où il vient, après deux secondes, donc suffisamment de temps pour que la requête s'effectue complètement et que l'utilisateur puisse voir le message qui accompagne le bon déroulement de la requête.

2.2.3 Ajouter des tâches

Pour ajouter de nouvelles tâches, il a fallu ajouter sur la page de modification de la liste des tâches un autre formulaire qui redirigait vers une autre page web "task_form.php". Ce formulaire contient trois champs : un de type "text" pour le titre, un de type "date" pour la date limite et un de type "select" pour sélectionner un degré de priorité parmi les trois proposés. En plus de ceux-la, il y a également un bouton "submit" pour envoyer les données et un bouton "reset" pour les réinitialiser. Lorsque l'on a entré nos données et cliqué sur le bouton, toutes sont envoyées à "task_form.php" pour être traitées. Sur cette nouvelle page, on vérifie déjà que toutes les données sont présentes puis on lance une nouvelle connexion à notre base de données et on va envoyer une requête à celle-ci pour ajouter une nouvelle entrée. On utilise les données que l'on a reçues en POST pour préciser le titre, la date limite et la priorité de cette nouvelle requête. L'identifiant et la valeur "achieved" ne sont pas nécessaires étant donné que l'une s'auto-incrémente et que l'autre prend une valeur par défaut. On utilise également une fonction appelée "real_escape_string()" pour être sur que les données qui nous ont été envoyées sont juste de simples valeurs et pas un code qu'un utilisateur malveillant voudrait injecter dans la base de données pour en prendre le contrôle. Si tout se passe bien, on affiche un petit message pour signifier que la requête a été effectuée. Sinon, on affiche la ou les erreur(s). Finalement, on ferme la connexion à la base de données et une balise "meta" est de nouveau là pour nous rediriger vers notre site d'origine à la fin du traitement des données.

2.2.4 La mise en page

Un fichier CSS sont utilisés dans le projet. Les seules singularités de ce fichier sont la façon dont il est utilisé pour mettre en avant les différentes priorités dans la liste des tâches et comment il est utilisé pour transformer les boutons. Premièrement, à chaque cellule vide correspond une valeur de priorité dans le tableau et à chacune de ces cellules est attribuée une classe en fonction de la priorité de la tâche avec laquelle elle est associée. Pour différencier ces cellules selon leur priorité, il suffisait alors de modifier les propriétés de la classe à laquelle elles appartiennent. On modifie donc ici la couleur de l'arrière-plan de la cellule ("background-color") : trois couleurs, vert, orange et rouge, pour trois niveaux de priorité, peu important, important et très important. Deuxièmement, on modifie l'aspect du bouton. On en cache le texte et on le rend carré. Une classe a également été assigné aux boutons "Valider" pour que ceux-ci apparaissent comme deux croix vertes cochées et une autre classe aux boutons "Supprimer" pour que eux apparaissent comme des cases rouges avec des croix.

2.2.5 Nettoyage automatique de la base de données

Il ne manque maintenant plus qu'un moyen d'éliminer les tâches une fois qu'elles ont dépassées leur date limite. Le moyen le plus simple de le faire est de mettre en place un événement MySQL. Celui-ci s'enclenche à un intervalle de temps donné et effectue une ou plusieurs actions. Pour le créer, il suffit d'aller dans la console MySQL sur le serveur et d'envoyer la commande suivante :

CREATE EVENT autoclean ON SCHEDULE EVERY '1' DAY STARTS '2017-05-08 23:59:00' DO UPDATE `ListeTaches` SET `achieved` = FALSE WHERE `dateline` < CURDATE() ; END

Celle-ci crée un nouvel événement "autoclean" qui s'enclenche chaque jour juste avant minuit et assigne la valeur 0 à tous les champs "achieved" où la date limite de la tâche est plus petite que la date actuelle, ce qui signifie qu'elle est passée. Le code est inspiré de l'exemple sur http://stackoverflow.com/questions/....

2.2.6 Mise en place de l'écran tactile

Il ne reste plus qu'à régler le Raspberry Pi relié à l'écran tactile de sorte que celui-ci lance la page web "show_list.php" au démarrage. Après avoir essayé de le faire avec le fichier "rc.local", qui effectue les commandes qu'il contient au démarrage, mais qui ne semblait pas vouloir marcher, l'environnement de démarrage "lxsession" à cette fois été utilisé. Il s'agit également d'un fichier texte situé dans le chemin "~/.config/lxsession/LXDE-pi/autostart" dans lequel la ligne suivante a été rentrée :

@chromium-browser --app=http://dev.gyre.ch/kilian.deternod/projetP/show_list.php

Pour que le navigateur Chromium se lance dès le démarrage sur la page "show_list" en plein écran. Le code est inspiré de l'exemple sur http://www.raspberrypi-spy.co.uk/20....

3. Résultats

Le résultats est disponible sur : dev.gyre.ch/kilian.deternod/projetP.... On peut dire que le projet est un succès. Les pages web marchent autant pour l'affichage que pour la modification de la liste, autant à l'ajout qu'à la suppression ou la validation. Tout fonctionne comme prévu du moins en surface car certains "bugs" ont été découverts bien tardivement dans l'avancement du projet et il est donc possible que d'autres subsistent. Le système fonctionne tout de même sur tous les navigateurs web testés (Google Chrome, Microsoft Edge, Firefox), à savoir tout de même que la fonction qui permet d'afficher un calendrier lorsqu'on choisit une date limite dans le formulaire ("input type=date") n'est pas disponible sous Firefox, c'est pourquoi un petit texte explicatif a également été mis en place afin d'informer l'utilisateur sur quel format de date choisir (ici jj.mm.aaaa). A part ce petit inconvénient, le projet fonctionne comme je l'avais espéré et certains points ont même dépassés mes attentes comme le fait d'avoir pu très simplement mettre en place le système de priorité ou encore la facilité d'utilisation sur l'écran tactile. Ainsi, même si je n'ai pas pu utiliser ce système dans ma vie de tous les jours car je n'en ai pas eu le temps, je serai prêt à l'utiliser quotidiennement après la reddition de ce projet.

4. Discussion

Le système fonctionne donc bien maintenant mais cela n'a pas toujours été le cas. En effet, l'apprentissage a été difficile sur ce projet. Etant donné que c'était la première fois que je m'attaquais à un projet d'une plus grande envergure et que j'ai la mauvaise habitude de foncer tête baissée dans mes projets et à écrire beaucoup de code sans forcer le tester au fur et à mesure, j'ai souvent passé beaucoup de temps à chercher des erreurs que je n'arrivais désespérément pas à trouver. Vu que je travaillais souvent sur un code qui dépendait d'encore plus de code ou même d'une base de données et que les erreurs ne s'affichaient pas directement, je restais souvent bloqué sur des problèmes basiques qui bloquaient complètement mon avancement. Cela a également fait que j'ai écrit des montagnes de codes que j'ai pu au final, après relecture, enlever ou remplacer par quelques lignes et de voir disparaître des heures et des heures de travail comme ça, c'est assez déprimant. Mais d'avoir au final un code complexe tout en restant condensé et qui fait exactement ce qu'il est censé faire tout en restant compréhensible, c'est la récompense finale et toutes ces heures "gâchées" qui auront tout de même servi à un apprentissage qui deviendra d'autant plus critique lorsque je m'attaquerais à des projets encore plus grands. Néanmoins, c'est lorsqu'on finit finalement ce qui était à faire que l'on remarque tout ce qui peut encore l'être. Par exemple, il serait possible d'installer un senseur de proximité pour n'allumer l'écran que lorsqu'une personne est présente pour éviter de gaspiller de l'électricité. De plus, il n'y a pas de moyen d'éteindre l'écran une fois qu'il est lancé à part de tirer la prise, celui-ci est bien sûr fait pour rester allumé tout le temps mais cela peut poser problème. Il serait également possible comme il a été dit dans la partie matériel de rendre ce projet portable assez facilement. A un niveau logiciel, un système de rappels automatiques par mail pourrait être mis en place pour informer l'utilisateur lorsqu'une tâche arrive à échéance. Il serait également préférable de mettre en place une sécurité pour éviter que n'importe qui puisse modifier la liste simplement en connaissant l'URL de la page. Bref, il est toujours possible d'aller plus loin mais je suis déjà entièrement satisfait de l'aboutissement de ce projet.

5. Conclusion

Pour finir, ce projet aura également servi à démystifier l'image que j'avais des bases de données et du Web en général. Lorsqu'on se rend compte que tout cela repose sur quelques langages de programmation et de description, on voit non seulement cet Internet que l'on utilise tout les jours d'une autre manière mais cela rend également moins inatteignables d'autres idées de projet que l'on peut avoir en tête. Je pense particulièrement aux bases de données qui peuvent facilement être intégrées à de petits projets, non seulement sur le Web mais également localement avec le langage Python par exemple.