{"id":406,"date":"2019-10-09T16:11:07","date_gmt":"2019-10-09T14:11:07","guid":{"rendered":"http:\/\/www.boichat.ch\/wordpress\/?p=406"},"modified":"2025-10-11T10:19:14","modified_gmt":"2025-10-11T08:19:14","slug":"python-flask-raspberry-pi","status":"publish","type":"post","link":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/","title":{"rendered":"Python Web Flask et SQLite pour le Raspberry Pi"},"content":{"rendered":"<p><strong><em> Date de la derni\u00e8re modification: 11 octobre 2025<\/em><\/strong><\/p>\n<p><span style=\"background-color: #ffff99;\">Cet article a \u00e9t\u00e9 soumis \u00e0 la r\u00e9daction de <a style=\"background-color: #ffff99;\" href=\"https:\/\/www.developpez.com\/\"><strong>developpez.com<\/strong><\/a>&nbsp;et a \u00e9t\u00e9 publi\u00e9 en mars 2020. <em>De nombreuses adaptations et suggestions des correcteurs y ont \u00e9t\u00e9 apport\u00e9es<\/em>. Il est aussi disponible au format PDF et avec un nouveau titre: <strong><a style=\"background-color: #ffff99;\" href=\"https:\/\/boichat.developpez.com\/tutoriels\/raspberry-pi-flask-sqlite\/\">Python Flask et SQLite pour le Raspberry Pi 3 ou 4 &#8211; exemples de communication avec des ESP32 ou ESP8266<\/a><\/strong>. <br><br><\/span><span style=\"background-color: #ccffff;\">En poursuivant sur ce m\u00eame sujet, il m&#8217;est venu \u00e0 l&#8217;id\u00e9e d&#8217;int\u00e9grer ce serveur Flask sur un NAS (Network Attached Storage) de Synology. L&#8217;article en travail se trouve ici m\u00eame: <a style=\"background-color: #ccffff;\" href=\"https:\/\/www.boichat.ch\/wordpress\/2020\/04\/13\/python-web-flask-sur-un-nas-synology\/\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>Python Web Flask sur un NAS (Synology)<\/strong><\/a>.&nbsp;<\/span> &nbsp;&nbsp;<\/p>\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Cet article contient un nombre incroyable de technologies, de langages de programmation et de sujets divers. Il y a ici tellement d&#8217;informations qu&#8217;il faudra plus les consid\u00e9rer comme des introductions \u00e0 tous les domaines trait\u00e9s.  <br><\/p>\n\n\n\n<p>Je ne suis pas moi-m\u00eame un expert en Python et je ma\u00eetrise plus des langages comme Java, C et C++. Etant  par cons\u00e9quent un &#8220;amateur pythonique&#8221;, il faudra sans doute consulter les sites de r\u00e9f\u00e9rence du langage. Cependant, sur les parties o\u00f9 j&#8217;ai moi-m\u00eame croch\u00e9 ou transpir\u00e9, j&#8217;ai \u00e9videmment documenter ces morceaux de code d\u00e9licats. Cela devrait suffire pour un d\u00e9butant en Flask! Le lecteur devra sans aucun doute se documenter mais avec des exemples tous parfaitement fonctionnels.<br><br>Quoique l&#8217;acc\u00e8s au GPIO du Raspberry Pi utilise souvent la version 2 du langage Python, je n&#8217;utiliserai ici que la version 3, donc la commande <strong>python3 <\/strong>sur le Raspberry Pi.<\/p>\n\n\n\n<p>Le <strong>Raspberry Pi<\/strong> est une plateforme exceptionnelle pour l&#8217;apprentissage du langage Python pour programmer le <strong>port GPIO<\/strong> o\u00f9 viendra se loger des composants comme des capteurs, des <strong>LEDs <\/strong>ou autres composants comme des buttons ou des buzzers. Ces aspects seront mineurs ici, car je me suis plus int\u00e9ress\u00e9 \u00e0 la communication avec l&#8217;ext\u00e9rieurs, c&#8217;est \u00e0 dire <strong>depuis <\/strong>des microcontr\u00f4leurs Wifi du type <strong>ESP32 <\/strong>ou <strong>ESP8266<\/strong>. Le <strong>Raspberry Pi<\/strong> peut \u00eatre consid\u00e9r\u00e9 comme un nano-ordinateur, alors qu&#8217;un <strong>ESP8266 <\/strong>bon march\u00e9 est le choix id\u00e9al pour mesurer, par exemple, une temp\u00e9rature dans une pi\u00e8ce et l&#8217;envoyer \u00e0 un Raspberry Pi avec le framework <strong>Flask<\/strong>.<\/p>\n\n\n\n<p>Le lecteur conna\u00eet sans doute d\u00e9j\u00e0 ce fameux nano-ordinateur dont voici un des mod\u00e8les&nbsp;:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"953\" height=\"622\" src=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2018\/10\/RaspberryPi1.jpg\" alt=\"\" class=\"wp-image-283\" srcset=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2018\/10\/RaspberryPi1.jpg 953w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2018\/10\/RaspberryPi1-300x196.jpg 300w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2018\/10\/RaspberryPi1-768x501.jpg 768w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2018\/10\/RaspberryPi1-90x60.jpg 90w\" sizes=\"(max-width: 953px) 100vw, 953px\" \/><figcaption><strong>Raspberry Pi 3 B<\/strong><\/figcaption><\/figure>\n\n\n\n<p>Quelques th\u00e8mes couverts sont (<strong><em>les titres ci-dessous sont des liens encr\u00e9s dans ce document :<\/em><\/strong>)<br><br>\n<span style=\"background-color: #FFFF00\">\n<strong>\n&#8211; <a href=\"#installation\">Installation de Python Flask sur le Raspberry Pi 3 ou 4<\/a><br>&#8211; <a href=\"#premutil\">Premi\u00e8re utilisation de Flask<\/a><br>&#8211; <a href=\"#demauto\">D\u00e9marrage automatique<\/a><br>&#8211; <a href=\"#premtest\">Premiers tests<\/a><br>&#8211; <a href=\"#pydev\">PyDev sous Windows Eclipse<\/a><br>&#8211; <a href=\"#templates\">Templates<\/a><br>&#8211; <a href=\"#relbuz\">Exemple avec Relais et Buzzer<\/a> (Fritzing)<\/strong><br><strong>&#8211; <\/strong><a href=\"#getesp32\"><strong>GET d&#8217;un ESP32 et des acc\u00e8s GPIO<\/strong><\/a><br><strong>&#8211; <a href=\"#fritzingesp32\">PIR et Buzzer<\/a> (Fritzing ESP32)<\/strong><br><strong>&#8211; <a href=\"#pireboot\">Pi Reboot avec Flask<\/a><\/strong><br><strong>&#8211; <a href=\"#getwindows\">Get depuis un PC Windows<\/a> (Python, Java)<br>&#8211; <a href=\"#sqliteflask\">SQLITE, Flask et temp\u00e9rature<\/a><br>&#8211; <a href=\"#postemail\">Envoi par courriel des temp\u00e9ratures extr\u00eames d&#8217;une journ\u00e9e<\/a><br><\/strong>\n<\/span>\n<\/p>\n\n\n\n<p>Nous allons montrer ici qu&#8217;un serveur <strong>Web Flask<\/strong> peut \u00eatre utilis\u00e9 comme outil de communication pour transf\u00e9rer des donn\u00e9es entre Raspberry Pi ou d&#8217;autres plateformes informatiques comme des Arduino, ESP voire des PC ou smartphones. <br><br>Des solutions en Java, avec un serveur Web et une base de donn\u00e9es SQLite, sont aussi possibles et d\u00e9crites dans mon livre publi\u00e9 chez <strong>Eyrolles<\/strong>, <strong><a rel=\"noreferrer noopener\" aria-label=\"UN LIVRE SUR JAVA, PYTHON, ECLIPSE ET LE RASPBERRY PI 3 (s\u2019ouvre dans un nouvel onglet)\" href=\"http:\/\/www.boichat.ch\/wpjrsp\/\" target=\"_blank\">UN LIVRE SUR JAVA, PYTHON, ECLIPSE ET LE RASPBERRY PI 3<\/a><\/strong> (exploitable aussi pour le Raspberry Pi 4). Ce livre est un peu de m\u00eame facture que cet article, mais avec \u00e9videmment plus de d\u00e9tails et de pr\u00e9cisions qu&#8217;ici. Je suis aussi actif sur le site <strong><a rel=\"noreferrer noopener\" href=\"https:\/\/www.developpez.net\/forums\/\" target=\"_blank\">developpez.net<\/a><\/strong>, en particulier dans les groupes d&#8217;int\u00e9r\u00eat d\u00e9di\u00e9s au&nbsp;<strong><a rel=\"noreferrer noopener\" href=\"https:\/\/www.developpez.net\/forums\/f2081\/general-developpement\/programmation-systeme\/embarque\/raspberry-pi\/\" target=\"_blank\">Raspberry Pi<\/a><\/strong> et \u00e0 l&#8217;<strong><a rel=\"noreferrer noopener\" href=\"https:\/\/www.developpez.net\/forums\/f2094\/general-developpement\/programmation-systeme\/embarque\/arduino\/\" target=\"_blank\">Arduino (ESP32 et ESP8266)<\/a><\/strong>. J&#8217;y ai d&#8217;ailleurs d\u00e9j\u00e0 publi\u00e9 les articles:<br>&#8211; <a rel=\"noreferrer noopener\" href=\"https:\/\/boichat.developpez.com\/tutoriels\/python\/micropython-pour-nodemcu-ESP8266\/\" target=\"_blank\"><strong>MicroPython pour le NodeMCU (ESP8266) avec Thonny (ao\u00fbt 2019)<\/strong><\/a><br>&#8211; <a rel=\"noreferrer noopener\" href=\"https:\/\/boichat.developpez.com\/tutoriels\/python\/apprendre-utiliser-pydev\/\" target=\"_blank\"><strong>PyDev, un IDE pour Python, sous Eclipse et pour le Raspberry Pi 3 (mars 2019)<\/strong><\/a>&nbsp;<\/p>\n\n\n\n<p>Cet article est consacr\u00e9 \u00e0 l\u2019installation et l&#8217;utilisation d&#8217;un serveur <strong>Web Flask<\/strong> pour le <strong>Raspberry Pi<\/strong>. En m\u00eame temps, il pourrait permettre aux lecteurs qui n\u2019ont presque aucune notion en programmation Python de se familiariser avec ce langage. De petits exemples simples en Python, soit pour le framework Flask, soit pour contr\u00f4ler les broches GPIO du Raspberry Pi, seront pr\u00e9sent\u00e9s et expliqu\u00e9s ici.<\/p>\n\n\n\n<p>L&#8217;installation a \u00e9t\u00e9 faite sur un Raspberry Pi 4, car je l\u2019avais re\u00e7u r\u00e9cemment, en Juillet 2019, \u00e0 sa sortie. Son utilisation sur un Raspberry Pi 3 B est identique.<\/p>\n\n\n\n<p>Je r\u00e9p\u00e9terai ici la d\u00e9finition de <strong>Flask <\/strong>qu&#8217;on trouve sur Wikipedia:<\/p>\n\n\n\n<p><em><strong>Flask est un framework open-source de d\u00e9veloppement web en Python. <\/strong><\/em> <em><strong>Son but principal est d&#8217;\u00eatre l\u00e9ger, afin de garder la souplesse de la programmation Python, associ\u00e9 \u00e0 un syst\u00e8me de templates. <\/strong><\/em> <em><strong>Il est distribu\u00e9 sous licence BSD2.<\/strong><\/em><\/p>\n\n\n\n<p>Nous assumerons ici que le lecteur a d\u00e9j\u00e0 son Raspberry Pi install\u00e9 avec le syst\u00e8me d\u2019exploitation standard <strong>Raspbian <\/strong>ou <strong>Buster <\/strong>et qu&#8217;il a d\u00e9j\u00e0 un peu d&#8217;exp\u00e9rience avec les broches GPIO, des capteurs ou autres mat\u00e9riels classiques d&#8217;un environnement Raspberry Pi. <br><br>Pour les ESP32 et ESP8266 utilis\u00e9s dans cette article, je ne donnerai aussi que peu d&#8217;explications sur les broches et leur utilisations. De simples recherches sur le Web nous permettront de d\u00e9couvrir les d\u00e9tails de montages pour des composants ou circuits \u00e9quivalents. Suivant les constructeurs il peut y a voir de petites diff\u00e9rences de notations et de num\u00e9rotations GPIO. Le lecteur pourra tr\u00e8s bien, avec un peu d&#8217;attention, choisir d&#8217;autres versions d&#8217;ESP.<\/p>\n\n\n\n<p>Comme j\u2019utilise mes <strong>Raspberry Pi<\/strong> sans \u00e9cran ni clavier, toutes les proc\u00e9dures d\u2019installation et de v\u00e9rification sont ex\u00e9cut\u00e9es dans un console du syst\u00e8me d\u2019exploration, le Raspian Buster ici. La console appara\u00eet chez moi \u00e0 partir d\u2019une connexion <strong>PuTTY <\/strong>sur un PC Windows 10. Tous les tests de pages accessibles sur le serveur Web <strong>Flask <\/strong>sont faites depuis un navigateur <strong>Chrome <\/strong>ou <strong>Firefox <\/strong>(mais doivent fonctionner aussi avec par exemple <strong>Edge <\/strong>ou <strong>Opera<\/strong>). L\u2019application Windows <strong>PuTTY <\/strong>peut \u00eatre install\u00e9e apr\u00e8s t\u00e9l\u00e9chargement depuis <a rel=\"noreferrer noopener\" aria-label=\"https:\/\/www.putty.org\/ (s\u2019ouvre dans un nouvel onglet)\" href=\"https:\/\/www.putty.org\/\" target=\"_blank\"><strong>https:\/\/www.putty.org\/<\/strong><\/a>.<\/p>\n\n\n\n<p>Attention \u00e0 la configuration du Raspberry Pi: il faudra s&#8217;assurer que le fuseau horaire est correctement d\u00e9fini. Nous pourrons faire la v\u00e9rification avec <strong>sudo raspi-config<\/strong>, le menu 4 (Localisation Options), ensuite I2 (Change Timezone) et mettre, par exemple, sur Europe et Paris. Si ce n&#8217;est pas juste, les dates en Python   seront d\u00e9cal\u00e9es et des heures incorrectes stock\u00e9es dans la base de donn\u00e9es SQLite.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">R\u00e9f\u00e9rences sur le Web<\/h3>\n\n\n<p class=\"western\">Il y a beaucoup de r\u00e9f\u00e9rences sur le Web et en voici quelques-unes pour bien d\u00e9buter:<\/p>\n<ul>\n<li><strong><a href=\"http:\/\/flask.palletsprojects.com\/en\/1.1.x\/\" target=\"_blank\" rel=\"noopener noreferrer\">Welcome to Flask<\/a><\/strong><\/li>\n<li><a href=\"https:\/\/blog.miguelgrinberg.com\/post\/the-flask-mega-tutorial-part-i-hello-world\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>The Flask Mega-Tutorial<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/realpython.com\/python-web-applications-with-flask-part-i\/\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>Real Python with Flask part i<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/realpython.com\/python-web-applications-with-flask-part-ii\/\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>Real Python with Flask part ii<\/strong><\/a><\/li>\n<\/ul>\n\n\n<h2 class=\"wp-block-heading\" id=\"installation\">Installation de Flask<\/h2>\n\n\n\n<p>Qui dit <strong>Flask<\/strong>, dit serveur Web. Donc la connaissance de l&#8217;adresse IP de notre Raspberry Pi est essentiel pour tous les acc\u00e8s de l&#8217;ext\u00e9rieur.  Une console <strong>PuTTY <\/strong>sur notre Pi se pr\u00e9sentera ainsi:<\/p>\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #f5f599; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 13px; white-space: pre-wrap;\">login as: pi\npi@192.168.1.143's password:\nLinux raspberrypi 4.19.50-v7l+ #895 SMP Thu Jun 20 16:03:42 BST 2019 armv7l\nThe programs included with the Debian GNU\/Linux system are free software;\nthe exact distribution terms for each program are described in the\nindividual files in \/usr\/share\/doc\/*\/copyright.\nDebian GNU\/Linux comes with ABSOLUTELY NO WARRANTY, to the extent\npermitted by applicable law.\nLast login: Fri Sep  6 09:07:26 2019 from 192.168.1.110\npi@raspberrypi:~ $\n<\/span><\/span><\/pre>\n\n\n<p>L\u2019adresse IP <strong>192.168.1.143<\/strong> du Raspberry Pi 4 a \u00e9t\u00e9 d\u00e9finie lors de l\u2019installation et peut \u00eatre attribu\u00e9e comme adresse IP fixe dans le routeur domestique.<\/p>\n\n\n\n<p>Si nous travaillions depuis un PC Linux, par exemple Ubuntu, nous pourrions alors utiliser la commande <strong>ssh <\/strong>\u00e9quivalente \u00e0 l\u2019application Windows PuTTY&nbsp;:<\/p>\n\n\n<p><span style=\"font-size: 20px;\"><strong><span style=\"background-color: #ffffff;\">ssh pi@192.168.1.143<\/span><\/strong><\/span><\/p>\n\n\n<p>Si notre Raspberry Pi n\u2019a pas \u00e9t\u00e9 install\u00e9 r\u00e9cemment, il faudrait tout d\u2019abord le mettre \u00e0 jour. Ces deux commandes peuvent \u00eatre ex\u00e9cut\u00e9es de toute mani\u00e8re, sans risque, pour des mises \u00e0 jour \u00e9ventuelles&nbsp;: <\/p>\n\n\n<div class=\"has-background\" style=\"background: #fff;\">\n<p><strong><span style=\"font-size: 20px;\">pi@raspberrypi ~ $ sudo apt-get update <\/span><\/strong><br><strong><span style=\"font-size: 20px;\">pi@raspberrypi ~ $ sudo apt-getupgrade<\/span><\/strong><\/p>\n<\/div>\n\n\n<p> Les deux commandes d\u2019installation requises pour <strong>Flask <\/strong>sont&nbsp;: <\/p>\n\n\n<div class=\"has-background\" style=\"background: #fff;\">\n<p><!--EndFragment--><span style=\"font-size: 20px;\"><strong>sudo apt-get install python-pip <br>sudo pip install flask<\/strong><\/span><\/p>\n<\/div>\n\n\n<p>Nous indiquerons aussi que le langage Python est pr\u00e9install\u00e9 et qu\u2019il est tout de m\u00eame conseill\u00e9 de l\u2019avoir d\u00e9j\u00e0 un peu utilis\u00e9. Pour les programmeurs du Raspberry Pi, c\u2019est le langage essentiel, en particulier pour d\u00e9velopper des scripts utilisant les broches GPIO et du mat\u00e9riel comme des capteurs de temp\u00e9rature, de mouvement, ou autres.<\/p>\n\n\n\n<p>Dans mon cas nous voyons que l\u2019utilitaire <strong>pip<\/strong>, un gestionnaire de paquets pour Python, ainsi que Flask sont d\u00e9j\u00e0 install\u00e9s&nbsp;:<\/p>\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #f5f599; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 15px; white-space: pre-wrap;\">pi@raspberrypi:~ $ sudo apt-get install python-pip\nReading package lists... Done\nBuilding dependency tree\nReading state information... Done\npython-pip is already the newest version (18.1-5+rpt1).\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\npi@raspberrypi:~ $ sudo pip install flask\nLooking in indexes: \n  https:\/\/pypi.org\/simple, https:\/\/www.piwheels.org\/simple\nRequirement already satisfied: \n  flask in \/usr\/lib\/python2.7\/dist-packages (1.0.2)\npi@raspberrypi:~ $\n<\/span><\/span><\/pre>\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"premutil\">Premi\u00e8re utilisation de Flask<\/h2>\n\n\n\n<p>Nous allons commencer par un HTTP GET, tout simple, sans param\u00e8tre et ensuite avec du code pour y ex\u00e9cuter des fonctions GPIO.<\/p>\n\n\n\n<p>Nous assumerons que le lecteur \u00e0 suffisamment de connaissance avec Linux et nous commencerons donc par cr\u00e9er un r\u00e9pertoire de travail pour nos scripts Python d\u00e9di\u00e9 \u00e0 Flask&nbsp;:<\/p>\n\n\n<p><strong>p<span style=\"font-size: 20px;\">i@raspberrypi:~ $ mkdir flaskeur<\/span><br><span style=\"font-size: 20px;\">pi@raspberrypi:~ $ cd flaskeur<\/span><br><span style=\"font-size: 20px;\">pi@raspberrypi:~\/flaskeur<\/span><\/strong><\/p>\n\n\n<p> <br>Nous allons cr\u00e9er un premier script Flask nomm\u00e9 <strong>salut_flaskeur.py<\/strong> comme ceci&nbsp;: <\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 14px; white-space: pre-wrap;\"># salut_flaskeur.py\nfrom flask import Flask\napp = Flask(__name__)\n@app.route('\/')\n   def home():\n   return \"Salut Flaskeur!\"\nif __name__ == '__main__':\n   app.run(host='0.0.0.0', port=5000, debug=True)\n<\/span><\/span><\/pre>\n\n\n\n<p>La fonction <strong>home() <\/strong>est d\u00e9finie par le mot cl\u00e9 <strong>def<\/strong>. Elle va simplement nous retourner le texte non format\u00e9 <strong>Salut Flaskeur<\/strong> et ceci pour le document racine de notre serveur Web qui est d\u00e9fini avec <strong>@app.route(&#8216;\/&#8217;<\/strong>).<\/p>\n\n\n\n<p>Si nous d\u00e9finissions un <strong>@app.route(&#8216;\/salut&#8217;)<\/strong>, nous devrions alors entrer, depuis par exemple un PC Windows, <a href=\"http:\/\/192.168.1.143:5000\/salut\"><strong>http:\/\/192.168.1.143:5000\/salut<\/strong><\/a> (voir ci-dessous) et un <a href=\"http:\/\/192.168.1.143:5000\/\"><strong>http:\/\/192.168.1.143:5000<\/strong><\/a> nous retournerait un <strong>Not Found<\/strong> comme tous autres URL autre ici qu&#8217;un <strong>\/salut<\/strong>. Le code d\u2019erreur <strong>404<\/strong>, qui correspond \u00e0 une page non trouv\u00e9e, sera pr\u00e9sente dans la fen\u00eatre de notre explorateur Internet et dans la console <strong>Putty <\/strong>de notre <strong>Raspberry Pi<\/strong>.<\/p>\n\n\n\n<p>Les autres instructions indiquent que c\u2019est une application Flask a d\u00e9marrer avec une entr\u00e9e <strong>main()<\/strong> classique de Python. Le port par d\u00e9faut de <strong>Flask <\/strong>est <strong>5000<\/strong>. Il est tout \u00e0 fait possible. Je ne mentionnerai pas ici le protocole <strong>HTTPS <\/strong>o\u00f9 il faudrait utiliser<strong> from OpenSSL import SSL<\/strong>.  <\/p>\n\n\n\n<p>Nous utiliserons le host <strong>0.0.0.0 <\/strong>afin de configurer le serveur Web Flask pour \u00eatre visible au travers du r\u00e9seau. Les sites de pr\u00e9sentation de Flask pour le Pi utilise souvent un simple <strong>app.run(debug=True)<\/strong> qui n\u00e9cessiterait de travailler en mode \u00e9cran avec clavier et souris, ou en mode VNC. Dans ce cas uniquement un acc\u00e8s <a href=\"http:\/\/127.0.0.1:5000\/\"><strong>http:\/\/127.0.0.1:5000<\/strong><\/a> sur la propre machine serait possible, donc avec par exemple le navigateur chromium-browser pr\u00e9install\u00e9 sur le Pi 4, navigateur que je n\u2019ai jamais utilis\u00e9.<\/p>\n\n\n\n<p>Attention \u00e0 l\u2019indentation correcte (sur deux des lignes ici ou j\u2019ai choisis 3 espaces) qui est n\u00e9cessaire pour le langage Python. PyDev sous Eclipse, que nous allons aborder rapidement, aidera beaucoup en pouvant forcer l&#8217;utilisation de tabulateurs.<\/p>\n\n\n\n<p>Travaillant moi-m\u00eame sous Linux bien avant l\u2019arriv\u00e9e de l\u2019\u00e9diteur GNU nano en l\u2019an 2000, je suis plus habitu\u00e9 \u00e0 utiliser l\u2019\u00e9diteur vi. Mais, dans une console, nous pouvons tr\u00e8s bien travailler avec l\u2019\u00e9diteur nano, qui est traditionnellement utilis\u00e9, et avec la commande&nbsp;:<\/p>\n\n\n\n<p><\/p>\n\n\n<p><span style=\"font-size: 20px;\"><strong>nano salut_flaskeur.py<\/strong><\/span><\/p>\n\n\n<p>Un <strong>Ctrl-C<\/strong> depuis Windows du code ci-dessus, suivi d\u2019un <strong>Ctlr-O<\/strong> ou\/et <strong>Ctrl-X<\/strong>, seront n\u00e9cessaires pour sauver le code et quitter. La commande<\/p>\n\n\n\n<p><\/p>\n\n\n<p><span style=\"font-size: 20px;\"><strong>cat salut_flaskeur.py<\/strong><\/span><\/p>\n\n\n<p>nous permettra de v\u00e9rifier que le contenu est correct avant d\u2019ex\u00e9cuter&nbsp;:<\/p>\n\n\n<p><strong><span style=\"font-size: 20px;\">python3 salut_flaskeur.py<\/span><\/strong><\/p>\n\n\n<p>qui nous donnera ceci&nbsp;:<\/p>\n\n\n\n<p><\/p>\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #f5f599; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 15px; white-space: pre-wrap;\">pi@raspberrypi:~\/flaskeur $ python3 salut_flaskeur.py\n * Serving Flask app \"flaskeur\" (lazy loading)\n * Environment: production\n   WARNING: Do not use the development server in a production environment.\n   Use a production WSGI server instead.\n * Debug mode: on\n * Running on http:\/\/0.0.0.0:5000\/ (Press CTRL+C to quit)\n * Restarting with stat\n * Debugger is active!\n * Debugger PIN: 108-533-113\n<\/span><\/span><\/pre>\n\n\n<p>Pour interrompre le serveur un <strong>Ctrl-C<\/strong> sera n\u00e9cessaire.<\/p>\n\n\n\n<p>Nous indiquerons \u00e0 nouveau que nous utilisons ici, pour cet article et sur le Raspberry Pi, la version 3 de Python, identifiable avec la commande <strong>python3 <\/strong>(<strong>python2<\/strong>, \u00e9quivalent \u00e0 <strong>python<\/strong>, serait pour la version 2) :<\/p>\n\n\n<p><span style=\"font-size: 20px;\"><strong>pi@raspberrypi:~\/flaskeur $ python3 -V<br>Python 3.7.3<\/strong><\/span><\/p>\n\n\n<p>Pour d\u00e9marrer le serveur Web Flask en arri\u00e8re plan et identifier qu\u2019il est effectivement actif avec la commande ps qui montre les processus actifs&nbsp;:<\/p>\n\n\n\n<p><\/p>\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #f5f599; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 15px; white-space: pre-wrap;\">pi@raspberrypi:~\/flaskeur $ python3 salut_flaskeur.py &amp;\n[1] 2211\npi@raspberrypi:~\/flaskeur $  * Serving Flask app \"flaskeur\" (lazy loading)\n * Environment: production\n   WARNING: Do not use the development server in a production environment.\n   Use a production WSGI server instead.\n * Debug mode: on\n * Running on http:\/\/127.0.0.1:5000\/ (Press CTRL+C to quit)\n * Restarting with stat\n * Debugger is active!\n * Debugger PIN: 108-533-113\nps\n  PID TTY          TIME CMD\n  711 pts\/0    00:00:00 bash\n 2211 pts\/0    00:00:00 python\n 2213 pts\/0    00:00:00 python\n 2216 pts\/0    00:00:00 ps\n<\/span><\/span><\/pre>\n\n\n<p><br>La commande&nbsp;:<br><\/p>\n\n\n<p><span style=\"font-size: 20px;\"><strong>sudo kill -9 2211 2213 <\/strong><\/span><\/p>\n\n\n<p>nous permettra de stopper les deux processus concern\u00e9s, c\u2019est \u00e0 dire le serveur Web. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"demauto\">D\u00e9marrage automatique par le Raspberry Pi<\/h3>\n\n\n\n<p>Au lancement du Raspberry Pi, il est possible d\u2019indiquer que notre Web serveur Flask se lancera automatiquement, sans besoin d\u2019une console pour le d\u00e9marrer. Notre <strong>salut_flaskeur.py<\/strong> est plus que primitif et il est \u00e0 esp\u00e9rer que le lecteur s\u2019attaquera \u00e0 la suite de cet article.<\/p>\n\n\n\n<p>Avec la commande:<\/p>\n\n\n<p><span style=\"font-size: 20px;\"><strong>sudo nano \/etc\/rc.local <\/strong><\/span><\/p>\n\n\n<p>nous ajouterons tout \u00e0 la fin le lancement en arri\u00e8re plan d\u2019<strong>httpserveur5000.sh<\/strong>&nbsp;<strong>F<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted wp-block-code center has-background\" style=\"background:#8ed1fc\">\u2026\u2026\u2026\u2026\u2026\u2026\u2026\u2026<br> if [ \"$_IP\" ]; then<br>   printf \"My IP address is %s\\n\" \"$_IP\"<br> fi<br> \/home\/pi\/flaskeur\/httpserveur5000.sh &amp;<br> exit 0<br><\/pre>\n\n\n\n<p>Nous devrons cr\u00e9er le script bash <strong>httpserveur5000.sh<\/strong> avec&nbsp;:<\/p>\n\n\n<p><span style=\"font-size: 20px;\"><strong>pi@raspberrypi:~\/flaskeur $ nano httpserveur5000.sh<\/strong><\/span><\/p>\n\n\n<p>et contenant ici les deux commandes: <\/p>\n\n\n<h2><span style=\"font-size: 20px;\"><strong>cd \/home\/pi\/flaskeur<\/strong><\/span><br><span style=\"font-size: 20px;\"><strong>python3 salut_flaskeur.py<\/strong><\/span><\/h2>\n\n\n<p>Le <strong>cd <\/strong>n\u2019est pas ici n\u00e9cessaire, mais plus tard, nous utiliserons dans nos script Flask d\u2019autres ressource venant de ce r\u00e9pertoire. Nous mettrons aussi les droits correctement, testerons le script <strong>bash<\/strong>, l\u2019interromprons avec <strong>Ctrl-C<\/strong>, avant de red\u00e9marrer le Pi avec un traditionnel <strong>sudo reboot<\/strong>&nbsp;:<\/p>\n\n\n\n<p><strong>chmod +x   httpserveur5000.sh<br>\/home\/pi\/flaskeur\/httpserveur5000.sh<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"premtest\">Premier test depuis notre PC<\/h2>\n\n\n\n<p>Nous utiliserons Chrome, Firefox ou notre navigateur Internet pr\u00e9f\u00e9r\u00e9 depuis notre PC avec l\u2019adresse <a href=\"http:\/\/192.168.1.143:5000\/\"><strong>http:\/\/192.168.1.143:5000\/<\/strong><\/a>. Nous verrons alors appara\u00eetre le texte dans la fen\u00eatre du navigateur Web&nbsp;:<\/p>\n\n\n<p><span style=\"font-size: 20px; background-color: #ffff00;\"><strong>Salut Flaskeur<\/strong><\/span><\/p>\n\n\n<p>Voil\u00e0&nbsp;! C\u2019est un bon d\u00e9but et cela fonctionne. Nous pourrions d\u00e9j\u00e0 ici modifier le port 5000, voir le texte ou encore d\u00e9finir un autre port et un autre fichier <strong>salut2_flaskeur.py<\/strong>. Les deux serveurs Web pourrait \u00eatre lanc\u00e9s simultan\u00e9ment, en parall\u00e8le, nous permettant de les avoir actifs en m\u00eame temps, par exemple pour des fonctionnalit\u00e9s diff\u00e9rentes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"pydev\">PyDev sous Windows Eclipse<\/h2>\n\n\n\n<p>Les lecteurs qui ont lu mon autre article, <strong><a rel=\"noreferrer noopener\" href=\"https:\/\/boichat.developpez.com\/tutoriels\/python\/apprendre-utiliser-pydev\/\" target=\"_blank\">PyDev, un IDE pour Python, sous Eclipse et pour le Raspberry Pi 3<\/a><\/strong>, pourront configurer leur Eclipse sur leur PC Windows &#8230; ou autre. C&#8217;est vraiment un plaisir avec le d\u00e9bogueur Python! <br>Lors de l&#8217;\u00e9criture de cet article, c&#8217;est seulement en y \u00e9crivant sa derni\u00e8re partie que je me suis rendu compte qu&#8217;il \u00e9tait incontournable. En r\u00e9visant la partie sur les Templates qui suit, j&#8217;ai tout de suite int\u00e9gr\u00e9 le code dans mon projet Eclipse.<\/p>\n\n\n\n<p>Les scripts <strong>Flask <\/strong>sont typiquement test\u00e9s avec des URL qui ressemblent \u00e0 quelque chose comme:<br><strong>http:\/\/127.0.0.1\/system<\/strong><br>que nous verrons ci-dessous. Le fichier <strong>Flask <\/strong>sera ici <strong>system.py<\/strong> qui sera d\u00e9pos\u00e9 dans un projet Python sous Eclipse, unique, pourquoi pas, pour tous les scripts Python de cet article. Afin de pouvoir activer depuis Eclipse l&#8217;URL detest, nous ajouterons une ligne comment\u00e9 avec le caract\u00e8re #:<br><strong># http:\/\/127.0.0.1\/system<\/strong><br>et ceci tout au d\u00e9but du fichier, sur la premi\u00e8re ligne. Cela nous permettra avec le pointeur de la souris et en pressant la touche Ctrl, de nous voir pr\u00e9senter un menu o\u00f9 nous pourrons activer cette page Web, et ceci dans une fen\u00eatre d&#8217;Eclipse, \u00e0 droite de nos autres fichiers en \u00e9dition sous Eclipse. C&#8217;est tout simplement g\u00e9ant!   <\/p>\n\n\n\n<p>Sous Eclipse et Windows, comme indiquer dans l&#8217;article r\u00e9f\u00e9renc\u00e9 ci-dessus, il est possible de d\u00e9velopper en Python avec diff\u00e9rentes versions. Pour <strong>Flask<\/strong>, comme indiquer au d\u00e9but, j&#8217;ai choisi la version 3. Sous Eclipse il est possible de d\u00e9finir plusieurs configurations. Il sera plus facile de choisir la m\u00eame version 3 que celle d\u00e9finie dans le <strong>PATH <\/strong>de Windows. Au premier test de notre fichier Python Flask sous Eclipse, nous pourrions remarquer que <strong>Flask <\/strong>manque et une installation <strong>pip <\/strong>pour Python sous Windows serait requit:<\/p>\n\n\n<p><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">C:\\Users\\jb&gt;python -m pip install flask<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">Collecting flask<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">Downloading https:\/\/files.pythonhosted.org\/packages\/<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">&#8230;<\/span><\/strong><\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"templates&quot;\">Flask Templates<\/h2>\n\n\n\n<p>Le terme <strong>Template <\/strong>ici est utilis\u00e9 pour indiquer que nos script Python Flask vont \u00eatre d\u00e9finis une fonctionnalit\u00e9 de Flask permettant de pr\u00e9senter de jolies pages \u00e9crites en HTML contenant des parties variables<\/p>\n\n\n\n<p>Nous allons tout d\u2019abord \u00e9crire un script Python Flask pour pr\u00e9senter l\u2019information g\u00e9n\u00e9rale sur notre Raspberry Pi. Pour commencer il faut cr\u00e9er un sous-r\u00e9pertoire qui contiendra le fichier html utiliser par cette technologie de Templates&nbsp;:<\/p>\n\n\n<h2><strong><span style=\"font-size: 20px;\">pi@raspberrypi:~ $ pwd<\/span><\/strong><br><strong><span style=\"font-size: 20px;\">\/home\/pi<\/span><\/strong><br><strong><span style=\"font-size: 20px;\">pi@raspberrypi:~ $ cd flaskeur\/<\/span><\/strong><br><strong><span style=\"font-size: 20px;\">pi@raspberrypi:~\/flaskeur $ mkdir templates<\/span><\/strong><\/h2>\n\n\n<p>Moi-m\u00eame j\u2019aime bien travailler sur mon PC Windows. J\u2019utilise l\u2019\u00e9diteur <strong>Notepad++<\/strong> (r\u00e9f\u00e9rence: <a rel=\"noreferrer noopener\" label=\"https:\/\/notepad-plus-plus.org\/ (s\u2019ouvre dans un nouvel onglet)\" href=\"https:\/\/notepad-plus-plus.org\/\" target=\"_blank\">Notepad++<\/a>), vraiment cool et je l\u2019associe \u00e0 <strong>WinSCP <\/strong>et <strong>PuTTY<\/strong>. WinSCP est un outil pour Windows qui permet de transf\u00e9rer des fichiers entre un PC et un Raspberry Pi, voire l&#8217;inverse pour des sauvegardes (r\u00e9f\u00e9rence: <strong><a rel=\"noreferrer noopener\" aria-label=\" (s\u2019ouvre dans un nouvel onglet)\" href=\"https:\/\/winscp.net\/eng\/docs\/lang:fr\" target=\"_blank\">https:\/\/winscp.net\/eng\/docs\/lang:fr<\/a><\/strong>) alors que <strong>PuTTY <\/strong>nous permet de travailler depuis le PC, comme si \u00e9tions dans une console <strong>bash <\/strong>du Raspberry Pi (r\u00e9f\u00e9rence: <strong><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/www.putty.org\/ (s\u2019ouvre dans un nouvel onglet)\" href=\"https:\/\/www.putty.org\/\" target=\"_blank\">https:\/\/www.putty.org\/<\/a><\/strong>).<\/p>\n\n\n\n<p>Pour cet article, j\u2019ai d\u00e9fini un r\u00e9pertoire <strong>D:\\RaspberryPi4\\PythonFlask<\/strong> sur mon PC Windows. Ce r\u00e9pertoire est automatiquement ouvert dans <strong>WinSCP <\/strong>car d\u00e9fini une fois dans sa configuration.<\/p>\n\n\n\n<p>Avec sa jolie syntaxique pour Python et d\u2019autres langages, je pr\u00e9f\u00e8re <strong>Notepad++<\/strong> sur le PC \u00e0 nano sur le Raspberry Pi (rappel&nbsp;: je travaille sans \u00e9cran ni clavier, ni avec un client VNC). Cette mani\u00e8re de faire me permet  conserver facilement une sauvegarde de mon code. Pour de petite corrections sur le Raspberry Pi, j\u2019utilise de pr\u00e9f\u00e9rence<strong> vi<\/strong> que je ma\u00eetrise, sans m\u00eame y r\u00e9fl\u00e9chir, depuis plus de 30 ans. Je ne dois pas oublier de repasser le code sur le PC avec <strong>WinScp<\/strong>, en s\u00e9lectionnant tous les fichiers et le sous-r\u00e9pertoire <strong>flaskeur<\/strong>, les dates me montrant d\u2019ailleurs si les fichiers sont identiques.<\/p>\n\n\n\n<p>Dans le r\u00e9pertoire <strong>flaskeur<\/strong> du Raspberry Pi, nous allons donc \u00e9crire un fichier <strong>system.py<\/strong> contenant&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre style=\"padding: 8.5px; \nfont-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; \nborder-radius: 4px; margin-top: 0px; margin-bottom: 9px; \nline-height: 18px; word-break: break-all; word-wrap: break-word; \nwhite-space: pre-wrap; \nbackground-color: #99ffff; \nborder: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\">\n<span style=\"font-size: 16px; white-space: pre-wrap;\">#Test avec \"http:\/\/127.0.0.1:5001\/system\"\n\nfrom flask import Flask, render_template\nimport platform\napp = Flask(__name__)\n \n@app.route(\"\/system\")\ndef hello():\n  uname = platform.uname()\n  thisdict = {\n    \"title\": \"Flask script system.py\",\n    \"hello\": \"Hello Fred\"\n  }\n  thisdict.update(uname._asdict())\n\n  return render_template('system.html', templateData = thisdict)\n \nif __name__ == \"__main__\":\n  app.run(host='0.0.0.0', port=5001, debug=True\n<\/span><\/span><\/pre>\n<\/pre>\n\n\n\n<p>Et dans le sous-r\u00e9pertoire <strong>templates <\/strong>nous d\u00e9poserons le fichier <strong>system.html<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre style=\"padding: 8.5px; \nfont-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; \nborder-radius: 4px; margin-top: 0px; margin-bottom: 9px; \nline-height: 18px; word-break: break-all; word-wrap: break-word; \nwhite-space: pre-wrap; \nbackground-color: #99ffff; \nborder: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\">\n<span style=\"font-size: 16px; white-space: pre-wrap;\">&lt;!DOCTYPE html&gt;\n   &lt;head&gt;\n      &lt;title&gt;Sans titre pour l'instant&lt;\/title&gt;\n   &lt;\/head&gt;\n\n   &lt;body&gt;\n      &lt;table&gt;\n        {% for key, value in templateData.items() %}\n          &lt;tr&gt;\n            &lt;td&gt;{{key}}&lt;\/td&gt;\n            &lt;td&gt;{{value}}&lt;\/td&gt;\n          &lt;\/tr&gt;\n        {% endfor %}\n      &lt;\/table&gt;\n   &lt;\/body&gt;\n&lt;\/html&gt;\n<\/span><\/span><\/pre>\n<\/pre>\n\n\n\n<p>On se r\u00e9f\u00e9rera \u00e0 la documentation de <strong>Flask <\/strong>et des <strong>Templates <\/strong>pour les d\u00e9tails et les constructions telles que les {{}}.<\/p>\n\n\n\n<p>Le code qui pr\u00e9c\u00e8de est relativement simple, \u00e0 l&#8217;exception sans doute de sa syntaxe, et il peut \u00eatre directement v\u00e9rifi\u00e9 sur le <strong>Raspberry Pi<\/strong>. Par contre, si nous d\u00e9sirions l&#8217;\u00e9tendre, avec du code Python, il serait \u00e9videmment recommand\u00e9 de le d\u00e9velopper sur un PC Windows avec <strong>PyDev<\/strong>. Le bouton <strong>Run <\/strong>sous Eclipse va d\u00e9marrer le serveur Web Flask en montrant la console d&#8217;ex\u00e9cution tout en en bas, si configur\u00e9 ainsi. La premi\u00e8re ligne de commentaire contient la r\u00e9f\u00e9rence URL <strong>http:\/\/127.0.0.1:5001\/system<\/strong> \u00e0 utiliser et \u00e0 entrer dans un explorateur Web. Avec 127.0.0.1, c\u2019est \u00e0 dire localhost, nous restons sur le PC pour tester notre script Flask. Nous r\u00e9p\u00e9terons, encore une fois ici, qu&#8217;Eclipse permet de naviguer avec la souris sur les mots <strong>http <\/strong>ou <strong>system<\/strong>, avec la touche <strong>Ctrl <\/strong>enfonc\u00e9e, afin de se voir pr\u00e9senter un menu permettant d&#8217;activer le navigateur Web interne \u00e0 Eclipse, et voir le r\u00e9sultat dans une nouvelle fen\u00eatre int\u00e9gr\u00e9e! Avec PyDev, nous ne pourrons pas utiliser le r\u00e9pertoire de travail <strong>D:\\RaspberryPi4\\PythonFlask<\/strong> sur notre PC Windows, car il sera int\u00e9gr\u00e9 \u00e0 un r\u00e9pertoire projet de notre espace de travail Eclipse (c\u2019est expliqu\u00e9 dans l\u2019article <strong><a href=\"https:\/\/boichat.developpez.com\/tutoriels\/python\/apprendre-utiliser-pydev\/\">PyDev, un IDE pour Python, sous Eclipse et pour le Raspberry Pi 3 (mars 2019)<\/a><\/strong>).<\/p>\n\n\n\n<p>Pour d\u00e9marrer ce server Web Flask, c\u2019est \u00e0 dire <strong>system.py<\/strong>, sur le Raspberry Pi dans le r\u00e9pertoire <strong>flaskeur <\/strong>(un &amp; additionnel, pour un d\u00e9marrage en arri\u00e8re plan, est possible \u00e9videmment) il nous faudra un<strong>:<\/strong> <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python3 system.py<\/code><\/pre>\n\n\n\n<p>En ex\u00e9cutant sur un PC Windows par exemple avec notre explorateur favori: <br><strong>http:\/\/192.168.1.143:5001\/system <\/strong><br>Nous recevrons ceci sur deux colonnes:: <\/p>\n\n\n<p><span style=\"font-family: 'courier new', courier, monospace;\">title&nbsp; &nbsp;Flask script system.py<\/span><br><span style=\"font-family: 'courier new', courier, monospace;\">hello&nbsp; &nbsp;Hello Fred<\/span><br><span style=\"font-family: 'courier new', courier, monospace;\">system&nbsp; Linux<\/span><br><span style=\"font-family: 'courier new', courier, monospace;\">node&nbsp; &nbsp; raspberrypi<\/span><br><span style=\"font-family: 'courier new', courier, monospace;\">release 4.19.50-v7l+<\/span><br><span style=\"font-family: 'courier new', courier, monospace;\">version #895 SMP Thu Jun 20 16:03:42 BST 2019<\/span><br><span style=\"font-family: 'courier new', courier, monospace;\">machine armv7l<\/span><br><span style=\"font-family: 'courier new', courier, monospace;\">processor<\/span><\/p>\n\n\n<p>La cl\u00e9 <strong>processor <\/strong>n&#8217;est pas pr\u00e9sente. Nous pourrions le v\u00e9rifier sous Python 3 dans une console du <strong>Raspberry Pi.<\/strong> Le lecteur pourra s&#8217;amuser \u00e0 introduire d&#8217;autres valeurs dans le dictionnaire <strong>render_template()<\/strong> pass\u00e9 \u00e0 <strong>system.html<\/strong> et les extraire s\u00e9par\u00e9ment pour les formater diff\u00e9remment en HTML avec, par exemple, des bord voire du css.  <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"relbuz\">Sch\u00e9ma Fritzing \u2013 Relais et Buzzer<\/h2>\n\n\n\n<p>En d\u00e9posant juste un <strong>relais <\/strong>et un <strong>buzzer <\/strong>alarme sur notre Raspberry Pi, c&#8217;est suffisant pour les tests de nos prochaines applications <strong>Flask<\/strong>. Nous verrons qu&#8217;il est aussi tr\u00e8s facile d&#8217;acc\u00e9der en Python \u00e0 des composants <strong>GPIO <\/strong>\u00e0 partir de scripts Flask.  <\/p>\n\n\n\n<p>Le sch\u00e9ma Fritzing pr\u00e9sent\u00e9 ici est d\u00e9di\u00e9 au Raspberry Pi. Nous noterons que les broches des Raspberry Pi 3 ou Pi 4 sont identiques.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"974\" src=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/relaisbuzzer_bb-1024x974.png\" alt=\"\" class=\"wp-image-509\" srcset=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/relaisbuzzer_bb-1024x974.png 1024w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/relaisbuzzer_bb-300x285.png 300w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/relaisbuzzer_bb-768x731.png 768w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/relaisbuzzer_bb.png 1050w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>La num\u00e9rotation des pins se trouvent sur de nombreux site comme  <br><a rel=\"noreferrer noopener\" aria-label=\"https:\/\/pi4j.com\/1.2\/pins\/model-3b-plus-rev1.html (s\u2019ouvre dans un nouvel onglet)\" href=\"https:\/\/pi4j.com\/1.2\/pins\/model-3b-plus-rev1.html\" target=\"_blank\"><strong>https:\/\/pi4j.com\/1.2\/pins\/model-3b-plus-rev1.html<\/strong><\/a> que j&#8217;utilise moi-m\u00eame pour la programmation du GPIO en Java. J&#8217;ai la bonne habitude de toujours indiquer le num\u00e9ro de la broche physique dans mon code , c&#8217;est \u00e0 dire correspondant au mode GPIO.BOARD (voir ci-dessous). Si l&#8217;on prend le fil jaune pour le contr\u00f4le du relais, c&#8217;est le huiti\u00e8me broche physique \u00e0 droite, num\u00e9rot\u00e9e paire, donc la broche num\u00e9ro 16.<br><br>En utilisant deux broches de terre diff\u00e9rentes (<strong>GND<\/strong>), nous n&#8217;aurons pas de platine d&#8217;essai. Le <strong>buzzer<\/strong>, le <strong>relais <\/strong>et le <strong>Raspberry Pi <\/strong>ayant des broches m\u00e2les, il suffit de se procurer des fils avec deux connecteurs femelles. J&#8217;utilise volontiers des fils de 20 cm qui me permettent, en particulier pour le <strong>buzzer<\/strong>, de placer mes composants assez \u00e9loign\u00e9s du bo\u00eetier  contenant le <strong>Raspberry Pi<\/strong>. Je n&#8217;indique pas ici comme connecter le relais \u00e0 la partie haute tension, proc\u00e9dure qui n\u00e9cessitera les pr\u00e9cautions n\u00e9cessaires voire une v\u00e9rification par un \u00e9lectricien.  <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_30\">D\u00e9clencher un relais sur le Raspberry Pi<\/h2>\n\n\n\n<p>Avant de pouvoir visionner l&#8217;\u00e9tat d&#8217;un relais avec Flask,  nous allons commencer par un petit exercice avec ce composant GPIO \u00e9lectrique (5\/220 Volt) que nous allons enclencher ou d\u00e9clencher chaque 4 secondes. Ce logiciel sera ext\u00e9rieur au serveur Flask Web et aussi \u00e9crit en langage Python&nbsp;(fichier <strong>relayonoff.py<\/strong> d\u00e9pos\u00e9 dans le r\u00e9pertoire <strong>flaskeur<\/strong> de notre Raspberry Pi) :<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre style=\"padding: 8.5px; \nfont-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; \nborder-radius: 4px; margin-top: 0px; margin-bottom: 9px; \nline-height: 18px; word-break: break-all; word-wrap: break-word; \nwhite-space: pre-wrap; \nbackground-color: #99ffff; \nborder: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\">\n<span style=\"font-size: 16px; white-space: pre-wrap;\"># coding: utf-8\nimport RPi.GPIO as GPIO\nimport time\n\nRelayPin = 16    # broche physique 16 \n\ndef setup():\n  GPIO.setmode(GPIO.BOARD)         # Num\u00e9ro GPIO par broche physique\n  GPIO.setup(RelayPin, GPIO.OUT)   # RelayPin en mode output\n\n  try:\n    while True:\n      GPIO.output(RelayPin, GPIO.HIGH)\n      f = open(\"relaystate.txt\", \"w\")\n      f.write(\"ON\")\n      f.close()\n      time.sleep(4)\n\n      GPIO.output(RelayPin, GPIO.LOW)\n\n      f = open(\"relaystate.txt\", \"w\")\n      f.write(\"OFF\")\n      f.close()\n\n      time.sleep(4)\n  except KeyboardInterrupt:  # Interruption avec 'Ctrl+C'\n     GPIO.cleanup()                   # Ressources lib\u00e9r\u00e9es\n\nif __name__ == '__main__':   # D\u00e9marrage en Python\n  setup()\n<\/span><\/span><\/pre>\n<\/pre>\n\n\n\n<p>Le script Python va ouvrir et fermer le relais, chaque 10 secs, et stocker l\u2019\u00e9tat dans un fichier nommer <strong> relaystate.txt<\/strong>. Le contenu de ce dernier n\u2019a rien de plus que 2 ou 3 caract\u00e8res et cela va simplifier la g\u00e9n\u00e9ration de la page HTML. Pour conna\u00eetre l\u2019\u00e9tat du relais, il n\u2019est pas possible d\u2019ouvrir cette broche <strong>GPIO <\/strong>en <strong>GPIO.IN<\/strong>. C\u2019est la raison d\u2019utiliser ici un fichier qui est un m\u00e9canisme simple.<\/p>\n\n\n\n<p>Le script Python Flask <strong>relaystate.py <\/strong>se pr\u00e9sentera ainsi&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background\"><code>from flask import Flask, render_template\nimport datetime\napp = Flask(__name__)\n\n@app.route(\"\/relaystate\")\ndef hello():\n   file = open(\"relaystate.txt\", \"r\") \n   state = file.readline()\n   \n   templateData = {\n      'title' : 'Relay state!',\n      'relaystate': state\n      }\n   return render_template('relaystate.html', **templateData)\n\nif __name__ == \"__main__\":\n   app.run(host='0.0.0.0', port=80, debug=True)<\/code><\/pre>\n\n\n\n<p>Avec son template relaystate.html&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code has-background\"><code>&lt;!DOCTYPE html>\n   &lt;head>\n      &lt;title>{{ title }}&lt;\/title>\n   &lt;\/head>\n\n   &lt;body>\n      &lt;h3>Relay state: {{ relaystate }}&lt;\/h2>\n   &lt;\/body>\n&lt;\/html><\/code><\/pre>\n\n\n\n<p>C\u2019est incroyablement simple, presque trop simple, il faut le reconna\u00eetre. Suivant l\u2019\u00e9tat du relais nous aurons une r\u00e9ponse pour <strong>http:\/\/192.168.1.143\/relaystate<\/strong> tel que&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Relay state: ON<\/code><\/pre>\n\n\n\n<p>Le lecteur pourrait s&#8217;amuser \u00e0 \u00e9crire un formulaire qui fait basculer l&#8217;\u00e9tat du relais sur clic du bouton de soumission et avec la page qui est rafra\u00eechie. L&#8217;\u00e9tat pourrait \u00eatre sauvegard\u00e9e dans une base de donn\u00e9es SQLite, que nous allons traiter plus loin.<\/p>\n\n\n\n<p>Pour pouvoir visionner cette page il nous faudra les deux commandes&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> python3 relayonoff.py &amp;\n sudo python3 relaystate.py &amp;<\/code><\/pre>\n\n\n\n<p>Nous noterons ici qu\u2019\u00e0 chaque lancement de processus avec <strong>&amp;<\/strong>, un message appara\u00eet avec le num\u00e9ro du process entre crochet. Il est possible de l\u2019utiliser pour la commande <strong>sudo kill -9<\/strong>. Pour <strong>relayonoff.py<\/strong>, le <strong>kill <\/strong>ne va pas ex\u00e9cuter <strong>GPIO.cleanup()<\/strong>. Nous pourrions alors avoir au prochain d\u00e9marrage un<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>relayonoff.py:9: RuntimeWarning: This channel is already in use, continuing anyway.  \nUse GPIO.setwarnings(False) to disable warnings.\nGPIO.setup(RelayPin, GPIO.OUT)   # RelayPin en mode output<\/code><\/pre>\n\n\n\n<p>qui indique que la ressource est utilis\u00e9e. Le script fonctionnera quand m\u00eame et le lecteur pourrait rajouter un<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GPIO.setwarnings(False) <\/code><\/pre>\n\n\n\n<p>au d\u00e9but de <strong>def setup()<\/strong>.<\/p>\n\n\n\n<p>Avant de continuer la lecture la lecture de cet article ou de modifier la pr\u00e9sentation de cette page livr\u00e9e par le serveur Flask Web, il nous faudra stopper les deux processus concern\u00e9s. Une commande <strong>ps <\/strong>nous montrera les 3 processus \u00e0 stopper \u00e9ventuellement avec un <strong>sudo kill -9<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"getesp32\">Un exemple Flask avec GET d&#8217;un ESP32 et des acc\u00e8s GPIO<\/h2>\n\n\n\n<p>Avant de passer \u00e0 des exemple contenant des param\u00e8tres GET, nous commencerons par un exercice impliquant un <strong>ESP32 <\/strong>qui va d\u00e9tecter le passage d\u2019un chat et envoyer l\u2019\u00e9v\u00e9nement sur un Raspberry Pi.<br>La s\u00e9quence compl\u00e8te est ainsi d\u00e9finie: <br><\/p>\n\n\n\n<ul><li><strong>L&#8217;ESP32 d\u00e9tecte un mouvement avec un capteur PIR<\/strong><\/li><li><strong>Il envoie une requ\u00eate \/beep au serveur Web Flask<\/strong><\/li><li><strong>Ce dernier g\u00e9n\u00e8re un son sur le buzzer du Raspberry Pi<\/strong><\/li><li><strong>Une pause de 10 secs sur l&#8217;ESP32 permettra de se d\u00e9placer \u00e0 la fen\u00eatre, sans bruit, pour identifier le passage \u00e9ventuel d&#8217;un chat<\/strong><\/li><li><strong>Un son variable ultrasonique r\u00e9pulsif est g\u00e9n\u00e9r\u00e9 sur le buzzer de l&#8217;ESP32.  <\/strong><\/li><\/ul>\n\n\n\n<p> Nous commencerons par le script Flask nomm\u00e9 <strong>beepalarm.py<\/strong>, sur le Raspberry Pi, correspondant \u00e0 notre GET d\u00e9sir\u00e9&nbsp;:  <\/p>\n\n\n\n<pre class=\"wp-block-preformatted wp-block-code center has-background\" style=\"background:#fff\">from threading import Lock<br>from flask import Flask<br>import time<br>import RPi.GPIO as GPIO<br><strong>lock = Lock()<\/strong><br> <br>app = Flask(__name__)<br>@app.route(\"\/beep\")<br>def beep():  <br>   <strong>with lock:<\/strong><br>      GPIO.setmode(GPIO.BOARD)<br>      GPIO.setup(12, GPIO.OUT)<br>      p = GPIO.PWM(12, 500)<br>      p.start(0)<br>      for dc in range(0, 101, 5):<br>         p.ChangeDutyCycle(dc\/2)<br>         p.ChangeFrequency(50+(2*dc))<br>         time.sleep(0.15)<br>      p.stop()<br>      GPIO.cleanup()<br> return ''<br> if __name__ == \"__main__\":<br>    app.run(host='0.0.0.0', port=8002, debug=True)<br><\/pre>\n\n\n\n<p>Ce script n\u2019a pas de <strong>template<\/strong> et c\u2019est un simple <strong>GET <\/strong>du protocol HTTP sans param\u00e8tre et sur le port 8002.<\/p>\n\n\n\n<p>Le <strong>lock <\/strong>est \u00e9quivalent \u00e0 un <strong>synchonized <\/strong>en Java! Le code inclus dans le bloc <strong>with lock<\/strong> sera bloqu\u00e9 jusqu&#8217;au <strong>GPIO.cleanup().<\/strong> Sans ce blocage plusieurs requ\u00eates Web simultan\u00e9es \u00e0 cette adresse produiraient une erreur car la ressource GPIO du GPIO ne serait pas unique. C&#8217;est facile \u00e0 tester avec deux fen\u00eatres de navigateur Web pour la m\u00eame adresse. <\/p>\n\n\n\n<p>Le PWM (Pulse Width Modulation, en fran\u00e7ais Modulation de largeur d&#8217;impulsion) permet de g\u00e9n\u00e9rer diff\u00e9rents types de sons. Pour nos besoins, nous nous sommes contenter de jouer avec le Duty Cycle (cycle de service) et la fr\u00e9quence.<\/p>\n\n\n\n<p>Le fichier script <strong>beepalarm.py<\/strong>  sera d\u00e9pos\u00e9 dans le r\u00e9pertoire <strong>flaskeur <\/strong>et d\u00e9marr\u00e9 avec&nbsp;:<br> <br><strong> pi@raspberrypi:~\/flaskeur $ python3 beepalarm.py<\/strong><\/p>\n\n\n\n<p>Un sudo n\u2019est pas n\u00e9cessaire pour le port 8002. Un test simple se fera avec <br><br><strong>http:\/\/192.168.1.143:8002\/beep<\/strong><br><br>dans un navigateur Web ext\u00e9rieur Au Raspberry Pi, et o\u00f9 aucun retour visible ne sera pr\u00e9sent\u00e9. <br>Qu&#8217;est qui n&#8217;est pas terrible terrible ici! Le <strong>\/beep<\/strong> ne re\u00e7oit aucun param\u00e8tre. Aucun moyen d&#8217;indiquer par exemple la g\u00e9n\u00e9ration d&#8217;un son diff\u00e9rent ou d&#8217;une longueur variable.  <br><\/p>\n\n\n<p><!--EndFragment--><\/p>\n<p>Nous allons maintenant pr\u00e9senter la partie ESP. C&#8217;est un ESP32-WROOM-32, mais un ESP8266 meilleur march\u00e9 irait aussi comme un Arduino avec WiFi.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"fritzingesp32\">Sch\u00e9ma Fritzing \u2013 ESP32 &#8211; PIR et Buzzer<\/h2>\n\n\n<p><!--EndFragment--><\/p>\n<p>Le sch\u00e9ma Fritzing correspondant au sketch <strong>esp32buzzerchat.ino<\/strong> ci-dessous se pr\u00e9sente ainsi&nbsp;:<\/p>\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"613\" height=\"1024\" src=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/esp32PirBuzzer_bb-613x1024.jpg\" alt=\"\" class=\"wp-image-511\" srcset=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/esp32PirBuzzer_bb-613x1024.jpg 613w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/esp32PirBuzzer_bb-180x300.jpg 180w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/09\/esp32PirBuzzer_bb.jpg 654w\" sizes=\"(max-width: 613px) 100vw, 613px\" \/><\/figure>\n\n\n\n<p>Le terme sketch est utilis\u00e9 pour indiqu\u00e9 que c\u2019est du code C\/C++ d\u00e9velopp\u00e9 et compil\u00e9 avec l\u2019IDE de l\u2019Arduino. Le type de carte pour l\u2019IDE sera l\u2019ESP32 Dev Module.<br>Le sketch esp32buzzerchat.ino qui suit fera le travail :<\/p>\n\n\n<div class=\"has-background\" style=\"background: #fff;\">\n<pre>#include &lt;WiFi.h&gt;\n#include &lt;HTTPClient.h&gt;\n\n\/\/13.5KHZ-19.5KHZ : Efficace pour repousser les animaux comme les souris, les rats, les chiens, les renards, les martres (belette) etc.\n\/\/19.5KHZ-24.5KHZ : Efficace pour repousser les animaux tels que les chats, les ratons laveurs, les blaireaux, les mouffettes etc.\n\nint freq = 2000;\nint channel = 0;\nint pinPir = 13;\nint resolution = 8;\nint pinBuzzer = 12;\n\nint httpCode = 1000;\n\nconst char* ssid = \"....\";\nconst char* pwd  = \"....\";\n  \nvoid setup() {\n  Serial.begin(9600);\n\n  Serial.print(\"Connexion \u00e0 \");\n  Serial.println(ssid);\n  WiFi.begin(ssid, pwd);\n  while (WiFi.status() != WL_CONNECTED) {\n    delay(200);\n    Serial.print(\".\");\n  }\n  \/\/Montre l'adresse IP\n  Serial.println(\"\");\n  Serial.println(\"WiFi connect\u00e9!\");\n  Serial.println(\"Adresse IP: \");\n  Serial.println(WiFi.localIP());\n  \n  ledcSetup(channel, freq, resolution);\n  ledcAttachPin(pinBuzzer, channel);\n\n  pinMode(pinPir,INPUT);\n}\n  \nvoid loop() { \n  bool isDetected = digitalRead(pinPir);\n \n  if (isDetected){\n    Serial.println(\"Pr\u00e9sence d\u00e9tect\u00e9e\");\n\n    HTTPClient http;\n    http.begin(\"http:\/\/192.168.1.143:8002\/beep\"); \n    http.addHeader(\"Content-Type\", \"text\/plain\");\n    httpCode = http.GET();\n    Serial.print(\"http return: \");\n    Serial.println(httpCode);\n    http.end();  \/\/free resources\n\n    delay(10000);\n    Serial.println(\"Start beep\");\n    ledcWrite(channel, 255);\n\n    int freq = 17000;  \/\/Hertz\n    while (freq &lt; 24000) {\n       ledcWriteTone(channel, freq);\n       freq += 100;\n       delay(80);\n    }\n    while (freq &gt; 17000) {\n       ledcWriteTone(channel, freq);\n       freq -= 100;\n       delay(60);\n    }\n\n    ledcWriteTone(channel, 0);\n    Serial.println(\"End of beep\"); \n    \n    delay(100);    \n  }\n \n  delay(100);\n}<\/pre>\n<\/div>\n\n\n<p>Le script Flask beep.py d\u00e9crit ci-dessus devra \u00eatre actif sur le Raspberry Pi afin de recevoir recevoir l\u2019\u00e9v\u00e9nement.<\/p>\n\n\n\n<p>La g\u00e9n\u00e9ration de fr\u00e9quences est similaire \u00e0 celle d\u00e9crite pr\u00e9c\u00e9demment pour le <strong>GPIO.PWM()<\/strong> dans le script Flask  <strong>beepalarm.py<\/strong> pr\u00e9c\u00e9dent. Les fr\u00e9quences utilis\u00e9es sont d\u00e9crites dans le sketch <strong>esp32buzzerchat.ino<\/strong> ci-dessus. Les spectres des sons \u00e9mis par le buzzer ont \u00e9t\u00e9 v\u00e9rifi\u00e9s avec l&#8217;application Android <strong>Spectroid <\/strong>et correspondant \u00e0 des r\u00e9pulsifs de chat qu&#8217;on trouve sur le march\u00e9.  <\/p>\n\n\n\n<p>Comme d\u00e9j\u00e0 indiqu\u00e9 en d\u00e9but d&#8217;article, je ne donnerai que peu de d\u00e9tails pour les <strong>ESP32 <\/strong>et <strong>ESP8266<\/strong>. Le code devrait aussi suffire sans trop d&#8217;explications. Nous voyons qu&#8217;une connexion au routeur est n\u00e9cessaire pour obtenir l&#8217;adresse <strong>IP <\/strong>de <strong>l&#8217;ESP32<\/strong>. Il faudra \u00e9videmment indiquer le <strong>ssid <\/strong>et le mot de passe (<strong>pwd<\/strong>) du WiFi et conna\u00eetre l&#8217;adresse <strong>IP<\/strong> du <em>Raspberry Pi<\/em> o\u00f9 se trouve notre serveur Web <strong>Flask<\/strong>. C&#8217;est le digitalRead(pinPir) qui nous indiquera la pr\u00e9sence d&#8217;un mouvement.Le lecteur pourra \u00e9videmment changer les sons \u00e9mis avec de jolies s\u00e9quences non &#8220;ultrasonic&#8221;.  <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"pireboot\">Un exemple Flask de reboot du Raspberry Pi<\/h2>\n\n\n\n<p>Nous restons dans le m\u00eame contexte d&#8217;un GET traditionnel avec le script que j&#8217;ai nomm\u00e9 <strong>reboot.py<\/strong>:<\/p>\n\n\n<pre>from flask import Flask\nimport os\napp = Flask(__name__)\n\n@app.route(\"\/reboot\")\ndef reboot(): \n#os.system('sudo reboot') fonctionne aussi\nos.system('sudo shutdown -r now')\n\nreturn ''\n\nif __name__ == \"__main__\":\napp.run(host='0.0.0.0', port=8080, debug=True)<\/pre>\n\n\n<p>Il est possible de choisir un autre port ou d&#8217;int\u00e9grer ce <strong>\/reboot<\/strong> dans un script plus complexe contenant d&#8217;autres entr\u00e9es.  Un serveur Web s\u00e9par\u00e9 sur 8080 et d\u00e9marr\u00e9 en parall\u00e8le avec d&#8217;autres serveurs ou applications est une solution que j&#8217;ai adopt\u00e9e o\u00f9 un:<br><\/p>\n\n\n<pre><span style=\"font-size: 20px;\"><strong>http:\/\/192.168.1.143:8080\/reboot <\/strong><\/span><\/pre>\n\n\n<p>qui relancerait le Raspberry Pi. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_28\">Notre reboot avec un get param\u00e9tris\u00e9<\/h2>\n\n\n\n<p>Les lecteurs ont sans doute d\u00e9j\u00e0 rencontr\u00e9 la forme:<\/p>\n\n\n<pre><span style=\"font-size: 20px; font-family: terminal, monaco, monospace;\"><strong>http:\/\/192.168.1.143:8080\/rebootd?delay=10<\/strong><\/span><span style=\"font-size: 20px;\"><strong>&nbsp;<\/strong><\/span><\/pre>\n\n\n<p>Cette forme de <strong>GET <\/strong>est plus pratique qu&#8217;un <strong>POST <\/strong>pour mettre en place un protocole entre Raspberry Pi, ESP ou autres syst\u00e8mes embarqu\u00e9s.  Dans le script <strong>esp32buzzerchat.ino<\/strong> que nous venons de pr\u00e9senter, nous avions un simple<strong> \/beep<\/strong>. Nous aurions pu lui ajouter un ou plusieurs param\u00e8tres pour indiquer diff\u00e9rentes \u00e9missions de son avec le buzzer du Raspberry Pi. Ce serait aussi un moyen d&#8217;y passer par exemple des indications de temp\u00e9ratures mesur\u00e9es.<\/p>\n\n\n\n<p>Ici nous allons permettre un <strong>reboot <\/strong>du Raspberry Pi apr\u00e8s un d\u00e9lais d&#8217;un nombre de secondes pass\u00e9 par param\u00e8tre. J&#8217;ai int\u00e9gr\u00e9 le script Flask correspondant dans le fichier <strong>reboot2.py<\/strong> :<\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 14px; white-space: pre-wrap;\">from flask import Flask, request\nimport os\nimport time\n\napp = Flask(__name__)\n\n@app.route('\/reboot')\ndef reboot():\n   #os.system('sudo reboot') \n   return 'reboot'\n\n@app.route('\/rebootd')\ndef rebootd():\n   delay = request.args.get('delay')\n   print (delay)\n   try:\n     secs = int(delay)\n   except TypeError:\n     secs = 0\n\n   time.sleep(secs)\n   #os.system('sudo reboot')\n   return 'reboot with delay of ' + str(secs) + ' secs'\n\nif __name__ == \"__main__\":\n   app.run(host='0.0.0.0', port=8080, debug=True)\n<\/span><\/span><\/pre>\n\n\n\n<p> <br>J&#8217;ai \u00e9videmment lanc\u00e9 pr\u00e9alablement <strong>python3 reboot2.py<\/strong> dans le r\u00e9pertoire <strong>flaskeur <\/strong>de mon Raspberry Pi. J&#8217;avais utilis\u00e9 \u00e0 l&#8217;origine la version 2 de Python, et j&#8217;ai d\u00fb corrig\u00e9 le print delay. C&#8217;est une des erreurs classiques. Il faut mettre les parenth\u00e8ses.<br><br>Apr\u00e8s avoir v\u00e9rifi\u00e9 les <strong>\/reboot<\/strong>, <strong>\/rebootd<\/strong> et <strong>\/rebootd?delay=5<\/strong> (5 secondes par exemple), nous pourrons remettre des <strong>return &#8221;<\/strong>, \u00f4ter les deux caract\u00e8res <strong>#<\/strong> de commentaire et v\u00e9rifier l&#8217;ex\u00e9cution r\u00e9elle des reboot du Raspberry Pi.<br><br>Le message <strong>reboot with delay of 5 secs<\/strong> viendra \u00e9videmment 5 secs plus tard que la requ\u00eate, si cette valeur de 5 est donn\u00e9e.<\/p>\n\n\n<p>Nous allons \u00e0 pr\u00e9sent montrer quelques exemples de GET ex\u00e9cut\u00e9s de l&#8217;ext\u00e9rieur:&nbsp;<\/p>\n<p><!--StartFragment--><\/p>\n\n\n<h3 class=\"wp-block-heading\" id=\"getwindows\">GET en Python depuis un PC Windows<\/h3>\n\n\n<p>Le code qui suit a \u00e9t\u00e9 inclus dans le script&nbsp;<strong>pcget1.py<\/strong>&nbsp;sur notre PC Windows. C&#8217;est un exemple tout simple d&#8217;un <strong>GET<\/strong> en Python qu&#8217;on retrouvera facilement sur le Web. Il pourra \u00eatre&nbsp;personnalis\u00e9 \u00e0 souhait et est utilisable sur d&#8217;autres plate-formes voire sur un autre Raspberry Pi. La librairie Python \u00e0 rechercher sera <strong>urllib<\/strong>.&nbsp;<\/p>\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 16px; white-space: pre-wrap;\">import urllib.request\nurl = \"http:\/\/192.168.1.143:8080\/rebootd?delay=2\"\nrequest = urllib.request.Request(url)\n\ntry:\n  response = urllib.request.urlopen(request)\n  data_content = response.read()\n  print(data_content.decode('utf-8'))\nexcept:\n  print(\"http:\/\/192.168.1.143:8080 not reached or error\")\n<\/span><\/span><\/pre>\n\n\n\n<p>Le 192.168.1.143:8080 et le <strong>rebootd<\/strong> sont les r\u00e9f\u00e9rences \u00e0 notre script pr\u00e9c\u00e9dent <strong>reboot2.py<\/strong> qui devra \u00eatre lanc\u00e9 sur notre Raspberry Pi. J&#8217;ai longtemps but\u00e9 sur le <strong>print(data_content)<\/strong> qui me retournait un b&#8217; (octet litt\u00e9ral) devant la r\u00e9ponse. En ajoutant decode(&#8216;utf-8&#8217;), j&#8217;ai \u00e9t\u00e9 satisfait!  <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">GET en Java depuis un PC Windows avec Eclipse<\/h3>\n\n\n<p>Le code qui suit fonctionne aussi. La classe&nbsp;<strong>LectureUrl<\/strong> est reprise tel quelle de mon livre, <strong><a href=\"http:\/\/www.boichat.ch\/wpjrsp\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"UN LIVRE SUR JAVA, PYTHON, ECLIPSE ET LE RASPBERRY PI 3 (s\u2019ouvre dans un nouvel onglet)\">UN LIVRE SUR JAVA, PYTHON, ECLIPSE ET LE RASPBERRY PI 3<\/a>&nbsp;<\/strong>avec l&#8217;URL modifi\u00e9. Je ne l&#8217;ai pas install\u00e9 ou essay\u00e9 sur un Raspberry Pi, mais ex\u00e9cut\u00e9e directement depuis Eclipse sur mon PC Windows.<\/p>\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 14px; white-space: pre-wrap;\">import java.net.*;\nimport java.io.*;\n\npublic class LectureUrl {\n  public static void main(String[] args) throws Exception {\n    URL notreUrl = \n      new URL(\"http:\/\/192.168.1.143:8080\/rebootd?delay=2\");\n    BufferedReader in = new BufferedReader(new \n    InputStreamReader(notreUrl.openStream()));\n    String inputLine;\n    while ((inputLine = in.readLine()) != null)\n      System.out.println(inputLine);\n      in.close();\n    }\n}\n<\/span><\/span><\/pre>\n\n\n\n<p>Dans la console d&#8217;Eclipse j&#8217;ai re\u00e7u un <strong>reboot with delay of 2 secs<\/strong> apr\u00e8s un d\u00e9lais de 2 secondes. J&#8217;ai \u00e9videmment lanc\u00e9 pr\u00e9alablement <strong>python reboot2.py<\/strong> dans le r\u00e9pertoire <strong>flaskeur <\/strong>de mon Raspberry Pi avec les <strong>sudo reboot<\/strong> en commentaire par simplicit\u00e9.<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sqliteflask\">SQLITE, Flask et temp\u00e9rature<\/h2>\n\n\n\n<p>Nous avons \u00e0 pr\u00e9sent tout le mat\u00e9riel Flask n\u00e9cessaire pour envoyer depuis l&#8217;ext\u00e9rieur, une temp\u00e9rature par exemple, et de la stocker sur un Raspberry Pi dans une base de donn\u00e9es SQLite. Cette derni\u00e8re est un choix naturel vu sa simplicit\u00e9.<br>Dans un second partie, nous y ajouterons des exemples de code pour envoyer ces temp\u00e9ratures avec diff\u00e9rents langages, comme Python, C\/C++ ou Java, et qui d\u00e9pendent de la plateforme o\u00f9 se situe le capteur de temp\u00e9rature.<\/p>\n\n\n<h3>Cr\u00e9ation d&#8217;une base de donn\u00e9es et d&#8217;une table<\/h3>\n<p>Le site de r\u00e9f\u00e9rence SQLite se trouve ici:&nbsp;&nbsp;<strong><a href=\"https:\/\/www.sqlite.org\/index.html\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/www.sqlite.org\/index.html<\/a><\/strong>.&nbsp;<\/p>\n<p>Dans mon livre, <strong><a href=\"http:\/\/www.boichat.ch\/wpjrsp\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"UN LIVRE SUR JAVA, PYTHON, ECLIPSE ET LE RASPBERRY PI 3 (s\u2019ouvre dans un nouvel onglet)\">UN LIVRE SUR JAVA, PYTHON, ECLIPSE ET LE RASPBERRY PI 3<\/a>,&nbsp;<\/strong>un chapitre entier est d\u00e9di\u00e9 \u00e0 <strong>SQLite<\/strong> pour le langage Java. Je ne peux \u00e9videmment pas faire de m\u00eame ici, voire encore plus pour les d\u00e9butants en <strong>SQL.&nbsp;<br>Repris de Wikipedia: SQL pour sigle de Structured Query Language (en fran\u00e7ais langage de requ\u00eate structur\u00e9e) est un langage informatique normalis\u00e9 servant \u00e0 exploiter des bases de donn\u00e9es relationnelles.<\/strong><\/p>\n<p>Je vais utiliser ici la m\u00eame strat\u00e9gie, c&#8217;est \u00e0 dire l&#8217;<strong><a href=\"http:\/\/sqlitebrowser.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">explorateur SQLite DB Browser<\/a><\/strong>&nbsp;\u00e0 installer sur un PC Windows. Nous pourrons alors mettre en place notre base de donn\u00e9es, qui est un fichier, d\u00e9finir la ou les tables n\u00e9cessaires, et copier ce fichier sur le Raspberry Pi, avec WinSCP, dans le r\u00e9pertoire o\u00f9 nous aurons le code Python, Flask ou non, voire d&#8217;autres langages, pour jouer avec nos temp\u00e9ratures.<\/p>\n<p>La d\u00e9finition de la table et de ses champs va d\u00e9pendre de l&#8217;usage qu&#8217;on en fera et aussi de se faciliter la t\u00e2che pour les enregistrements et ensuite les r\u00e9cup\u00e9rer pour les convertir dans diff\u00e9rents formats. Comme nous utiliserons principalement Python, une attention particuli\u00e8re sera n\u00e9cessaire pour les donn\u00e9es concernant les dates et les heures. Il faudra aussi savoir par exemple si une pr\u00e9cision \u00e0 la seconde est suffisante, ce qui en principe n&#8217;est pas n\u00e9cessaire pour une temp\u00e9rature, et si le client nous passe cette information. Il y a plein d&#8217;alternatives et de choix, comme de ne pas d\u00e9finir la date et l&#8217;heure c\u00f4t\u00e9 client et de laisser le Raspberry Pi y mettre les valeurs lors de la r\u00e9ception d&#8217;un \u00e9v\u00e9nement sous forme de GET.&nbsp;<\/p>\n<p>Le script Python <strong>sqlitecreate1.py<\/strong> qui suit nous montre la cr\u00e9ation d&#8217;une table <strong>events <\/strong>qui nous permettra de stocker nos enregistrements d&#8217;\u00e9v\u00e9nements:<\/p>\n<p><!--EndFragment--><\/p>\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 14px; white-space: pre-wrap;\">import sqlite3\nfrom datetime import datetime\n\nsqliteConnection = sqlite3.connect('SQLite_Python.db')\ncursor = sqliteConnection.cursor()\n\nsqlite_create_table_query = \\\n  '''CREATE TABLE events (nameevent TEXT NOT NULL, \\\n  namesource TEXT NOT NULL, value REAL NOT NULL, \\\n  thedate TEXT NOT NULL, thetime TEXT NOT NULL);'''\ncursor.execute(sqlite_create_table_query)\n\nnow = datetime.now()\nda = now.strftime(\"%d\/%m\/%Y\")\nti = now.strftime(\"%H:%M:%S\")\n\nsqlite_insert_with_param = \\\n  \"\"\"INSERT INTO 'events'('nameevent', 'namesource', \\\n  'value', 'thedate', 'thetime') VALUES (?, ?, ?, ?, ?);\"\"\"\n\ndata_tuple = ('temperature', 'esp32a', 23.1, da, ti)\ncursor.execute(sqlite_insert_with_param, data_tuple)\nsqliteConnection.commit()\n<\/span><\/span><\/pre>\n\n\n\n<p>Ce script a \u00e9t\u00e9 d\u00e9velopp\u00e9 avec <strong>Notepad++<\/strong>, test\u00e9 sur un PC dans une console <strong>CMD <\/strong>et ceci dans le r\u00e9pertoire de nos scripts <strong>Flask <\/strong>qui viennent parfois du Raspberry Pi avec <strong>WinSCP<\/strong>.<\/p>\n\n\n\n<p>J&#8217;aime bien <strong>le DB Browser SQLite<\/strong> (<strong><a href=\"https:\/\/sqlitebrowser.org\/dl\/\">son site officiel est ici<\/a><\/strong>). On pourra le t\u00e9l\u00e9charger et l&#8217;installer sur son PC et suivant son syst\u00e8me d&#8217;exploitation. Il nous permettrais de cr\u00e9er \u00e0 la main une nouvelle base de donn\u00e9es, de nouvelles tables, de les adapter ou de les corriger. La consultation, la correction ou l&#8217;effacement des donn\u00e9es est vraiment simple:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"422\" src=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser1-1024x422.jpg\" alt=\"\" class=\"wp-image-893\" srcset=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser1-1024x422.jpg 1024w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser1-300x124.jpg 300w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser1-768x317.jpg 768w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser1.jpg 1721w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption><strong>Structure de la base de donn\u00e9es<\/strong><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"990\" height=\"525\" src=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser2.jpg\" alt=\"\" class=\"wp-image-894\" srcset=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser2.jpg 990w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser2-300x159.jpg 300w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/11\/DBbrowser2-768x407.jpg 768w\" sizes=\"(max-width: 990px) 100vw, 990px\" \/><figcaption><strong>Contenu avec un enregistrement de test<\/strong><\/figcaption><\/figure>\n\n\n\n<p>Si nous ex\u00e9cutons une seconde fois ce script <strong>sqlitecreate1.py<\/strong>, il ne fonctionnera pas, car la base de donn\u00e9es, c&#8217;est \u00e0 dire le fichier <strong>SQLite_Python.db<\/strong> existera d\u00e9j\u00e0. Il faudrait effacer le fichier o\u00f9 tester sa pr\u00e9sence, voire demander d&#8217;effacer toutes les donn\u00e9es. L&#8217;<strong>INSERT INTO<\/strong> est juste l\u00e0 pour v\u00e9rifier un enregistrement. On pourra effacer l&#8217;entr\u00e9e avec le <strong>DB Browser SQLite<\/strong> avant de le d\u00e9poser sur le Pi pour \u00eatre utilis\u00e9 dans nos scripts <strong>Flask<\/strong>.  <\/p>\n\n\n\n<p>Nous avons choisi de s\u00e9parer la date de l&#8217;heure de la journ\u00e9e. Cela pourra simplifier notre logiciel en particulier pour r\u00e9cup\u00e9rer des donn\u00e9es d&#8217;une journ\u00e9e particuli\u00e8re. Le type <strong>TEXTE <\/strong>est un choix, nous aurions pu utiliser <strong>REAL <\/strong>ou <strong>INTEGER<\/strong>, ce dernier nous limiterait aux secondes, suffisant ici quand m\u00eame.<\/p>\n\n\n\n<p>Avec l&#8217;onglet <strong>Parcourir les donn\u00e9es,<\/strong> il est possible de cliquer sur une valeur sp\u00e9cifique de notre base de donn\u00e9es et de la modifier. Il faudra alors cliquer sur le bouton <strong>Appliquer<\/strong>. Ce sera pratique plus tard si nous voulions tester d&#8217;autres scripts Flask et v\u00e9rifier notre code avec des valeurs n\u00e9gatives pratiquement impossible \u00e0 g\u00e9n\u00e9rer dans notre chambre \u00e0 coucher!  <\/p>\n\n\n\n<p>Si l&#8217;on d\u00e9sirait utiliser <strong>mySQL <\/strong>en lieu et place de <strong>SQLite<\/strong>, il faudrait rechercher sur les sites d\u00e9di\u00e9s \u00e0 <strong>Python <\/strong>et <strong>Flask<\/strong>, et nous y d\u00e9couvririons du code comme:<\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 14px; white-space: pre-wrap;\">import mysql.connector\n\nmydb = mysql.connector.connect(\n  host=\"localhost\",\n  user=\"utilisateur\",\n  passwd=\"mot de passe\"\n)\n<\/span><\/span><\/pre>\n\n\n\n<p>Pour <strong>localhost<\/strong>,ce serait sur le Raspberry Pi (ou un PC) et une installation serait n\u00e9cessaire. <strong>SQLite <\/strong>n&#8217;a pas besoin d\u2019installation, puisque c&#8217;est un simple fichier. <strong>mySQL <\/strong>peut \u00e9videmment se trouver sur une autre machine, comme un NAS (un Serveur de stockage en r\u00e9seau), o\u00f9 <strong>localhost <\/strong>serait remplacer par une adresse IP configur\u00e9e et atteignable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sqliteflask\">SQLITE int\u00e9gration dans Flask<\/h2>\n\n\n\n<p>Nous allons passer \u00e0 pr\u00e9sent sur le Raspberry Pi. Notre fichier SQLite, <strong>SQLite_Python.db<\/strong>, pr\u00e9par\u00e9 ci-dessus sur notre PC, sera transf\u00e9r\u00e9 sur notre Pi avec <strong>WinScp <\/strong>et dans notre r\u00e9pertoire de travail <strong>\/home\/pi\/flaskeur<\/strong>. Je l&#8217;ai fait sur <strong>Buster <\/strong>avec&nbsp;les&nbsp;commandes:<\/p>\n\n\n<div class=\"has-background\" style=\"background: #fff;\">\n<p><strong><span style=\"font-size: 20px;\">pi@raspberrypi:~\/flaskeur ~ $ sudo apt-get update <\/span><\/strong><br><strong><span style=\"font-size: 20px;\">pi@raspberrypi:~\/flaskeur ~ $ sudo apt-getupgrade<br>pi@raspberrypi:~\/flaskeur $ sudo apt-get install sqlite3<br><\/span><\/strong><\/p>\n<\/div>\n\n\n<p>Ici, cela inclut la mise \u00e0 jour de <strong>Buster <\/strong>(ou <strong>Raspbian <\/strong>si install\u00e9). Il faudra entrer un <strong>Y <\/strong>majuscule lors de la requ\u00eate finale pour l&#8217;installation) Nous ferons la v\u00e9rification avec:<\/p>\n\n\n<p><strong><span style=\"font-size: 20px;\">pi@raspberrypi:~\/flaskeur ~ $ sqlite3 -version<\/span><\/strong><\/p>\n\n\n<p>Dans mon cas j&#8217;ai re\u00e7u un, 3.27.2 2019-02-25 16:06:06, indiquant la date de la version du logiciel <strong>sqlite3<\/strong>. La commande <strong>sqlite3 <\/strong>qui suit nous fait entrer dans un mode console o\u00f9 les commandes SQLIte sont disponibles:<\/p>\n\n\n<div class=\"has-background\" style=\"background: #fff;\">\n<p><strong><span style=\"font-size: 20px;\">pi@raspberrypi:~\/flaskeur $ sqlite3 SQLite_Python.db<br>SQLite version 3.27.2 2019-02-25 16:06:06<br>Enter &#8220;.help&#8221; for usage hints.<br>sqlite&gt; .tables<br>events<br>sqlite&gt; .schema events<br>CREATE TABLE events (nameevent TEXT NOT NULL, namesource TEXT NOT NULL, value REAL NOT NULL, thedate TEXT NOT NULL, thetime TEXT NOT NULL);<br>sqlite&gt; select * from events;<br>temperature|esp32a|23.1|31\/10\/2019|18:58:49<br>sqlite&gt;<br>pi@raspberrypi:~\/flaskeur $<\/span><\/strong><\/p>\n<\/div>\n\n\n<p>Les commandes .tables et .schema nous permettent de d\u00e9couvrir respectivement la seule table pr\u00e9sente dans notre base de donn\u00e9es et sa structure.<br>La commande select nous permet d&#8217;obtenir le contenu des donn\u00e9es enregistr\u00e9es. Il n&#8217;y a ici qu&#8217;un seul enregistrement: un \u00e9v\u00e9nement temp\u00e9rature de 23.1 re\u00e7u d&#8217;un ESP32 en octobre 2019 en fin de journ\u00e9e!<br><\/p>\n\n\n\n<p>De nombreux sites de pr\u00e9sentation de <strong>SQLite <\/strong>ou de tutoriels sont disponibles sur le Web, comme par exemple: <strong><a href=\"https:\/\/www.sqlitetutorial.net\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"https:\/\/www.sqlitetutorial.net\/ (s\u2019ouvre dans un nouvel onglet)\">https:\/\/www.sqlitetutorial.net\/<\/a><\/strong>.<\/p>\n\n\n\n<p>Il est pratique de d\u00e9finir dans le r\u00e9pertoire de travail du Raspberry Pi un certain nombres de script <strong>bash <\/strong>pour nous aider, comme par exemple <strong>selectall.sh<\/strong> qu&#8217;on aura <strong>chmod +x  selectall.sh<\/strong> pr\u00e9alablement. Il vous montrera le contenu de notre base de donn\u00e9es dans une console du Pi:<br><\/p>\n\n\n\n<p>pi@raspberrypi:~\/flaskeur $ cat selectall.sh<br> sqlite3 SQLite_Python.db &lt;&lt;EOF<br> select * from events<br> EOF<br><br>Un script comme <strong>deleteall.sh<\/strong> nous permettrait si n\u00e9cessaire d&#8217;effacer tous les enregistrements de la base de donn\u00e9es utilis\u00e9e dans cet article:<\/p>\n\n\n\n<p>pi@raspberrypi:~\/flaskeur $ cat deleteall.sh<br>\nsqlite3 SQLite_Python.db &lt;&lt;EOF<br>\ndelete from events<br>\nEOF<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sqliteflask\">Ev\u00e9nement: GET en Python<br><\/h2>\n\n\n\n<p>De la mani\u00e8re que notre script <strong>pcget1.py<\/strong> pr\u00e9c\u00e9dant, nous allons passer au Raspberry Pi un \u00e9v\u00e9nement temp\u00e9rature g\u00e9n\u00e9r\u00e9 depuis un PC Windows. Le code serait \u00e9videment identique, ou pratiquement, sur un autre syst\u00e8me supportant le langage Python, comme un autre Raspberry Pi! <br><br>Nous l&#8217;avons nomm\u00e9&nbsp;<strong>pcget2.py<\/strong>:<\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 16px; white-space: pre-wrap;\">import urllib.request\nurl = \"http:\/\/192.168.1.143:8080\/event?temperature=23.4\"\nrequest = urllib.request.Request(url)\nresponse = urllib.request.urlopen(request)\ndata_content = response.read()\nprint(data_content.decode('utf-8'))\n<\/span><\/span><\/pre>\n\n\n\n<p>L&#8217;entr\u00e9e <strong>\/event<\/strong> est un choix, comme le param\u00e8tre <strong>temperature<\/strong>. Le 23.4 est une valeur de test, puisque nous n&#8217;avons pas de capteur sur notre PC! <br>Nous avons d\u00e9fini la date et l&#8217;heure dans notre table <strong>SQLite <\/strong>et choisirons ici de laisser le serveur <strong>Flask <\/strong>responsable de g\u00e9n\u00e9rer ces deux valeurs.<br><br>Nous pourrions nous imaginer des clients, qui collectionnent des donn\u00e9es, bien avant de les transf\u00e9rer en paquet dans un serveur <strong>Flask<\/strong>. Dans ce cas la date et l&#8217;heure de l\u2019\u00e9v\u00e9nement serait n\u00e9cessaire.<\/p>\n\n\n\n<p>Le <strong>&#8220;http:\/\/192.168.1.143:8080\/event?temperature=23.4&#8221; <\/strong>pourrait \u00eatre remplac\u00e9 par <strong>&#8220;http:\/\/192.168.1.143:8080\/event?temperature=23.4&amp;namesource=PC&#8221;<\/strong> o\u00f9 <strong>namesource <\/strong>est le champ indiquant la source de l\u2019\u00e9v\u00e9nement, ici un PC! Nous verrons comment le serveur Flask pourra remplacer cette valeur, si elle n&#8217;est pas sp\u00e9cifi\u00e9e, par l&#8217;adresse IP du client, ce qui semble plus intelligent que le nom PC qu&#8217;il faudrait corriger par une valeur plus explicite!  <\/p>\n\n\n\n<p>Le d<strong>ecode(&#8216;utf-8&#8217;)<\/strong> est n\u00e9cessaire car data_content est une s\u00e9rie de bytes \u00e0 convertir. Si nous recevrions un string entour\u00e9 d&#8217;un <strong>b&#8221;,<\/strong> une suite d&#8217;octets litt\u00e9rales.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_31\">SQLite: Instruction INSERT<\/h2>\n\n\n\n<p>Nous avons \u00e0 pr\u00e9sent tout le mat\u00e9riel, le langage Python, son framework Flask et une base de donn\u00e9es SQLite, afin de r\u00e9cup\u00e9rer une temp\u00e9rature re\u00e7ue d&#8217;une m\u00e9thode GET de requ\u00eate HTTP et de la stocker.<br><br>Pour \u00eatre honn\u00eate, le code Python Flask nomm\u00e9 <strong>getevent1.py<\/strong> a \u00e9t\u00e9 compl\u00e8tement programm\u00e9 et test\u00e9 sur mon PC Windows avec Notepad++, et en parall\u00e8le ex\u00e9cut\u00e9 dans une console <strong>CMD<\/strong>, et tout ceci dans mon r\u00e9pertoire de travail <strong>D:\\RaspberryPi4\\PythonFlask<\/strong>. J&#8217;ai pu ainsi format\u00e9 proprement la code pour sa pr\u00e9sentation ici, dans cet article. Il est possible de le faire directement sur le Raspberry Pi, mais pour les d\u00e9butants, avec peu de connaissances <strong>SQL<\/strong>, voire de Python, un d\u00e9veloppement sous <strong>PyDev <\/strong>est \u00e0 conseiller vivement.<\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 16px; white-space: pre-wrap;\">from flask import Flask, request\nimport os\nimport time\nimport sqlite3\nfrom datetime import datetime\n\napp = Flask(__name__)\n\n@app.route('\/event')\ndef event():\n   tempera = request.args.get('temperature')\n   # print (tempera)\n   namesource = request.args.get('namesource')\n   # print (namesource)\n   ip_adress = request.remote_addr\n   # print(ip_adress)\n\n   if namesource is None: # Test if namesource is None\n     namesource = ip_adress\n\n   try:\n     ftempera = float(tempera)\n   except TypeError:\n     ftempera = 0\n\n   sqliteConnection = sqlite3.connect('SQLite_Python.db')\n   cursor = sqliteConnection.cursor()\n\n   now = datetime.now()\n   da = now.strftime(\"%d\/%m\/%Y\")\n   ti = now.strftime(\"%H:%M:%S\")\n\n   sqlite_insert_with_param = \"\"\"INSERT INTO 'events'('nameevent',\\\n                              'namesource', 'value', 'thedate', \\\n                              'thetime') VALUES (?, ?, ?, ?, ?);\"\"\"\n\n   data_tuple = ('temperature', namesource, ftempera, da, ti)\n   cursor.execute(sqlite_insert_with_param, data_tuple)\n   sqliteConnection.commit()\n\n   return 'Event temperature received with value of ' + \\\n          str(ftempera) + ' degrees'\n\nif __name__ == \"__main__\":\n   app.run(host='0.0.0.0', port=8080, debug=True)\n<\/span><\/span><\/pre>\n\n\n\n<p>Nous commencerons \u00e9videmment par une r\u00e9f\u00e9rence sur le Web comme <br><br><strong><a href=\"https:\/\/www.sqlitetutorial.net\/sqlite-python\/\">SQLite Python<\/a><\/strong> <br>avec plus sp\u00e9cifiquement<br><strong><a href=\"https:\/\/www.sqlitetutorial.net\/sqlite-python\/insert\/\">SQLite Python: Inserting Data<\/a><\/strong><\/p>\n\n\n\n<p>un tr\u00e8s bon tutoriel SQLite o\u00f9 nous trouverons le mat\u00e9riel indispensable pour programmer en SQL sous Python et Flask! Ce tutoriel sera aussi une aide pour comprendre certaines constructions utilis\u00e9es dans le code qui pr\u00e9c\u00e8de.<\/p>\n\n\n\n<p>Dans ce script <strong>getevent1.py<\/strong> vraiment simplifi\u00e9, il n&#8217;y a pratiquement aucun traitement d&#8217;erreurs. Lorsque j&#8217;ai eu termin\u00e9 les tests, j&#8217;ai ajout\u00e9 des # pour commenter les lignes <strong>print () <\/strong>en Python.<br>Par contre, si le param\u00e8tre <strong>namesource <\/strong>n&#8217;est pas pass\u00e9 dans le GET par le client, et ce n&#8217;est pas une mauvaise id\u00e9e du tout, il est remplac\u00e9 par l&#8217;adresse IP du client, disponible par le protocole de la requ\u00eate!<\/p>\n\n\n\n<p>Le gros avantage de tester sous Windows Notepad++ ou PyDev, est le fait que nous pouvons garder en permanence notre DB Browser for SQLite ouvert sur notre PC Windows, donc du fichier <strong>SQLite_Python.db<\/strong>, afin de v\u00e9rifier les donn\u00e9es enregistr\u00e9es dans la base de donn\u00e9es. Notre DB Browser a aussi une option d&#8217;export dans le menu Fichier suivi d&#8217;Export, o\u00f9 nous avons plusieurs choix comme le format SQL, CSV ou JSON. Avec le format SQL nous pourrions r\u00e9cup\u00e9rer les instructions SQL compl\u00e8te de cr\u00e9ation de la table events et de son contenu. Nous pourrions y d\u00e9couvrir par exemple:<\/p>\n\n\n\n<p><strong>INSERT INTO <\/strong><code><strong>events<\/strong><\/code><strong> (nameevent,namesource,value,thedate,thetime) VALUES (&#8216;temperature&#8217;,&#8217;192.168.1.110&#8242;,23.4,&#8217;24\/11\/2019&#8242;,&#8217;18:54:11&#8242;);<\/strong><\/p>\n\n\n\n<p>Cet INSERT en SQL pourrait \u00eatre adapt\u00e9 et copi\u00e9 dans la fen\u00eatre d&#8217;entr\u00e9e de l&#8217;onglet Ex\u00e9cuter SQL et enregistr\u00e9 dans la base de donn\u00e9es en utilisant le mini ic\u00f4ne play. C&#8217;est tr\u00e8s pratique pendant le d\u00e9veloppement de nos script Python pour v\u00e9rifier notre code, ici <strong>cursor.execute(sqlite_insert_with_param, data_tuple)<\/strong>, pour en faire les corrections et adaptations si n\u00e9cessaire. <\/p>\n\n\n\n<p>Le format <strong>CSV <\/strong>(Comma-separated values), est un format texte repr\u00e9sentant des donn\u00e9es tabulaires avec des valeurs s\u00e9par\u00e9es par des virgules. Tout en fin d\u2019article nous parlerons d\u2019id\u00e9e d\u2019extensions, o\u00f9 ce format serait utilisable, par exemple avec Excel, pour g\u00e9n\u00e9rer plus tard des graphiques d\u2019\u00e9v\u00e9nements ou de temp\u00e9ratures. <\/p>\n\n\n\n<p>Avec l&#8217;onglet <strong>Parcourir les donn\u00e9es<\/strong> il est aussi facile d&#8217;effacer facilement un ou plusieurs (Ctrl au clavier) enregistrements d&#8217;une base de donn\u00e9es qui risque de grossir inutilement pendant ces premiers tests.<\/p>\n\n\n\n<p>Sous Windows PC nous associerons \u00e9videmment l&#8217;extension <strong>.db<\/strong> \u00e0 notre DB Browswer for SQLite. Cela nous permettra d&#8217;ouvrir cet outil de navigation de notre base de donn\u00e9es, aussi bien depuis l&#8217;explorateur de fichiers de Windows, que depuis la liste des fichiers visibles dans le Project Explorer d&#8217;Eclipse.  <\/p>\n\n\n\n<p>Si nous sommes sur le Raspberry Pi, nous avons d\u00e9j\u00e0 montr\u00e9 comment visionner les enregistrement avec <strong>selectall.sh<\/strong>.<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"getesp32\">Les passages de personnes dans SQLITE<\/h2>\n\n\n\n<p>Pr\u00e9c\u00e9demment, avec notre <strong>ESP32 <\/strong>\u00e9quip\u00e9 d&#8217;un <strong>PIR <\/strong>(d\u00e9tecteur de mouvements), c&#8217;\u00e9tait notre sketch <strong>esp32buzzerchat.ino<\/strong>, nous avions inform\u00e9, avec un GET du protocole HTTP, le Raspberry Pi du passage de chats \u00e0 l&#8217;ext\u00e9rieur de notre maison. C&#8217;est \u00e9vident que nous allons retirer qui \u00e9met des ultrasons et qui commence \u00e0 nous casser les oreilles.<\/p>\n\n\n\n<p>Nous allons d\u00e9poser l&#8217;<strong>ESP32 <\/strong>pr\u00e9c\u00e9demment d\u00e9crit, dans un endroit o\u00f9 nous aimerions compter le nombre de passages de personnes, cette fois-ci, et avec le code du sketch <strong>esp32passage.ino<\/strong> suivant:<\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 16px; white-space: pre-wrap;\">#include &lt;WiFi.h&gt;\n#include &lt;HTTPClient.h&gt;\n\nint pinPir = 13;\nint resolution = 8;\n\nint httpCode = 200;\n\nconst char* ssid = \"....\";\nconst char* pwd  = \"....\";\n  \nvoid setup() {\n  Serial.begin(9600);\n\n  Serial.print(\"Connexion \u00e0 \");\n  Serial.println(ssid);\n  WiFi.begin(ssid, pwd);\n  while (WiFi.status() != WL_CONNECTED) {\n    delay(200);\n    Serial.print(\".\");\n  }\n  \/\/Montre l'adresse IP\n  Serial.println(\"\");\n  Serial.println(\"WiFi connect\u00e9!\");\n  Serial.println(\"Adresse IP: \");\n  Serial.println(WiFi.localIP());\n\n  pinMode(pinPir,INPUT);\n}\n  \nvoid loop() { \n  bool isDetected = digitalRead(pinPir);\n \n  if (isDetected){\n    Serial.println(\"Passage d\u00e9tect\u00e9\");\n\n    HTTPClient http;\n    http.begin(\"http:\/\/192.168.1.143:8002\/passage\"); \n    http.addHeader(\"Content-Type\", \"text\/plain\");\n    httpCode = http.GET();\n    Serial.print(\"http return: \");\n    Serial.println(httpCode);\n    http.end();  \/\/free resources\n\n    delay(5000);\n  }\n \n  delay(100);\n}\n<\/span><\/span><\/pre>\n\n\n\n<p>Il faudra \u00e0 nouveau ici indiquer le ssid et le mot de passe (pwd) du WiFi. Les nombreux <strong>print()<\/strong> vont nous aider \u00e9videmment dans la phase de d\u00e9veloppement. C&#8217;est \u00e0 nouveau le <strong>digitalRead(pinPir)<\/strong> qui nous indiquera la pr\u00e9sence d&#8217;un mouvement afin de g\u00e9n\u00e9rer le GET sur le Raspberry Pi.<br><br>Nous avons utiliser le port 8002 avec cet exemple sur l&#8217;ESP32 pour des questions pratiques: nous avons s\u00e9par\u00e9 cette partie d\u00e9di\u00e9e \u00e0 la d\u00e9tection de mouvements des autres consacr\u00e9es \u00e0 la temp\u00e9rature. Mais la base de donn\u00e9es est la m\u00eame, si nous la laissons dans le m\u00eame r\u00e9pertoire.<br>Le choix d&#8217;une pause de 5 secs pourrait permettre d&#8217;ignorer le passage d&#8217;une m\u00eame personne plusieurs fois durant cette p\u00e9riode, afin de limiter le nombre d&#8217;enregistrements.<\/p>\n\n\n\n<p>Nous allons donc modifier le script <strong>Flask <\/strong>pr\u00e9c\u00e9dent (<strong>getevent1.py<\/strong>) pour recevoir l\u2019\u00e9v\u00e9nement <strong>\/passage<\/strong> et le stocker pour statistique dans la table <strong>events <\/strong>de notre base de donn\u00e9e <strong>SQLite_Python.db<\/strong>. Oh, comme c&#8217;est simple maintenant ce script <strong>getevent2.py<\/strong> avec le port 8002:<\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 16px; white-space: pre-wrap;\">from flask import Flask, request\nimport os\nimport time\nimport sqlite3\nfrom datetime import datetime\n\napp = Flask(__name__)\n\n@app.route('\/passage')\ndef passage():\n   ip_adress = request.remote_addr\n\n   sqliteConnection = sqlite3.connect('SQLite_Python.db')\n   cursor = sqliteConnection.cursor()\n\n   now = datetime.now()\n   da = now.strftime(\"%d\/%m\/%Y\")\n   ti = now.strftime(\"%H:%M:%S\")\n\n   sqlite_insert_with_param = \"\"\"INSERT INTO 'events'('nameevent',\\\n                              'namesource', 'value', 'thedate', \\\n                              'thetime') VALUES (?, ?, ?, ?, ?);\"\"\"\n\n   data_tuple = ('movement', ip_adress, 0, da, ti)\n   cursor.execute(sqlite_insert_with_param, data_tuple)\n   sqliteConnection.commit()\n\n   return 'Event movement received'\n\nif __name__ == \"__main__\":\n   app.run(host='0.0.0.0', port=8002, debug=True)\n<\/span><\/span><\/pre>\n\n\n<p><!--EndFragment-->Si nous avons gard\u00e9 notre base de donn\u00e9es SQLite, sans effacer les donn\u00e9es de temp\u00e9rature, nous recevrons avec&nbsp;<strong>.\/selectall.sh<\/strong>, d\u00e9crit pr\u00e9c\u00e9demment, toutes les entr\u00e9es enregistr\u00e9es depuis le d\u00e9but, donc de sa cr\u00e9ation.<\/p>\n<p>Avec un SQL <strong>select<\/strong> sur un champ d\u00e9fini et une valeur sp\u00e9cifique comme celle-ci:<\/p>\n<p><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">pi@raspberrypi:~\/flaskeur $ sqlite3 SQLite_Python.db<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">SQLite version 3.27.2 2019-02-25 16:06:06<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">Enter &#8220;.help&#8221; for usage hints.<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">sqlite&gt; select theTime from events where nameevent = &#8216;movement&#8217;;<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">17:20:42<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">17:24:07<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">17:25:16<\/span><\/strong><br><strong><span style=\"font-family: 'courier new', courier, monospace; font-size: 14px;\">&#8230;&#8230;.<\/span><\/strong><\/p>\n<p>Nous aurions alors les heures pr\u00e9cises des mouvements d\u00e9tect\u00e9s. C&#8217;est ici que nous pourrions \u00e0 nouveau passer un peu de temps avec le tutoriel SQLite : <a href=\"https:\/\/www.sqlitetutorial.net\/\">https:\/\/www.sqlitetutorial.net\/<\/a>.<\/p>\n\n\n<p> <br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Collectionner les temp\u00e9ratures depuis un ESP8266 <\/h2>\n\n\n\n<p>Le sch\u00e9ma Fritzing pr\u00e9sent\u00e9 ici est pour un NodeMCU qui est \u00e9quivalent \u00e0 un ESP8266MOD DOIT.AM que j&#8217;ai moi-m\u00eame utilis\u00e9. <\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"594\" height=\"666\" src=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/12\/ESP8266_ds18B20_bb.jpg\" alt=\"\" class=\"wp-image-1090\" srcset=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/12\/ESP8266_ds18B20_bb.jpg 594w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/12\/ESP8266_ds18B20_bb-268x300.jpg 268w\" sizes=\"(max-width: 594px) 100vw, 594px\" \/><\/figure>\n\n\n\n<p>Le Dallas DS18B20 peut \u00eatre aliment\u00e9 en mode parasite, c&#8217;est \u00e0 dire avec \u00e0 la fois les broches marqu\u00e9es + et &#8211; sur la terre, o\u00f9 comme ici en mode normal. Je n&#8217;expliquerai pas en d\u00e9tails ces modes qu&#8217;on peut retrouver sur le Web. Il en va de m\u00eame avec le D2, o\u00f9 l&#8217;on retrouvera de nombreuses r\u00e9f\u00e9rences indiquant qu&#8217;il correspond on GPIO 4 indiqu\u00e9 dans le script ci-dessous. <\/p>\n\n\n\n<p>Le code, d\u00e9velopp\u00e9 avec l&#8217;IDE de l&#8217;Arduino et le type de carte <strong>Generic ESP8266 Module<\/strong> se pr\u00e9sentera ainsi (sketch <strong>esp8266tempflask.ino<\/strong>):<br><\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #99ffff; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 16px; white-space: pre-wrap;\">#include &lt;ESP8266WiFi.h&gt;\n#include &lt;WiFiClient.h&gt;\n#include &lt;ESP8266HTTPClient.h&gt;\n\n#include &lt;OneWire.h&gt;\n#include &lt;DallasTemperature.h&gt;\n\nconst char* ssid     = \"....\";\nconst char* password = \"....\";\n\n\/\/ GPIO du DS18B20\nconst int oneWireBus = 4;\n\nint httpCode = 200;\n\n\/\/ Setup a oneWire instance to communicate with any OneWire devices\nOneWire oneWire(oneWireBus);\n\n\/\/ Pass our oneWire reference to Dallas Temperature sensor \nDallasTemperature sensors(&amp;oneWire);\n\nvoid setup() {\n  \/\/ Start the Serial Monitor\n  Serial.begin(115200);\n  Serial.println(\"\");\n  Serial.println(\"esp8266tempflask started\");\n  \n  \/\/ Start the DS18B20 sensor\n  sensors.begin();\n\n  WiFi.begin(ssid, password);\n  Serial.println(\"\");\n\n  \/\/ Wait for connection\n  while (WiFi.status() != WL_CONNECTED) {\n    delay(500);\n    Serial.print(\".\");\n  }\n  Serial.println(\"\");\n  Serial.print(\"Connected to \");\n  Serial.println(ssid);\n  Serial.print(\"IP address: \");\n  Serial.println(WiFi.localIP());\n}\n\nvoid loop() {\n  sensors.requestTemperatures(); \n  float temperatureC = sensors.getTempCByIndex(0);\n  Serial.print(temperatureC);\n  Serial.println(\"\u00baC\");\n\n  char buffer[5];\n  String tempfl = dtostrf(temperatureC, 4, 1, buffer);\n  tempfl.trim();\n  Serial.println(\"http:\/\/192.168.1.143:8080\/event?temperature=\" + tempfl);\n\n  HTTPClient http;\n  http.begin(\"http:\/\/192.168.1.143:8080\/event?temperature=\" + tempfl); \n \n  http.addHeader(\"Content-Type\", \"text\/plain\");\n  httpCode = http.GET();\n  Serial.print(\"http return: \");\n  Serial.println(httpCode);\n  http.end();  \/\/free resources\n\n  int minutes = 5;\n  delay(1000*60*minutes);\n}\n<\/span><\/span><\/pre>\n\n\n\n<p>Nous avons garder le port 8080 et nous pourrons r\u00e9utiliser \u00e9videmment le script pr\u00e9c\u00e9dent <strong>getevent1.p<\/strong>y sur le Raspberry Pi en indiquant \u00e0 nouveau le ssid et le mot de passe (pwd) du WiFi.  En d\u00e9connectant l&#8217;<strong>ESP8266<\/strong> et le r\u00e9installant dans un endroit diff\u00e9rent, nous constaterons que cela fonctionne correctement. <\/p>\n\n\n\n<p>En \u00e9ditant le fichier <strong>\/etc\/rc.local<\/strong> sur le Raspberry Pi, nous pourrions y ajouter un script shell afin de d\u00e9marrer le script Python <strong>getevent1.py<\/strong> en arri\u00e8re plan et dans le r\u00e9pertoire o\u00f9 se situe le script et la base de donn\u00e9es. De cette mani\u00e8re, chaque fois que nous d\u00e9marrerons le Raspberry Pi, les donn\u00e9es de temp\u00e9rature collectionn\u00e9es sur divers ESP8266 ou ESP32, seront stock\u00e9es dans SQLite. <\/p>\n\n\n\n<p>Quand nous aurons suffisamment d&#8217;enregistrement, nous pourrions transf\u00e9rer le fichier <strong>SQLite_Python.db<\/strong> sur notre PC pour d\u00e9velopper le code qui va suivre, un peu plus \u00e9volu\u00e9, pour extraire des donn\u00e9es en SQL et envoyer un courriel avec des indications sur les temp\u00e9ratures mesur\u00e9es.   <br><br>Id\u00e9e d&#8217;extension: \u00e9crire un petit serveur Web sur l&#8217;ESP8266 pour modifier ces 5 minutes, l&#8217;adresse IP et le port du serveur Flask, et red\u00e9marrer <strong>esp8266tempflask.ino<\/strong>.<\/p>\n\n\n\n<p>Dans cette article nous avons utilis\u00e9 d&#8217;autres ports que le <strong>8080<\/strong>, afin de s\u00e9parer les fonctionnalit\u00e9s. Le port <strong>8002 <\/strong>a \u00e9t\u00e9 utilis\u00e9 pour d\u00e9tecter des mouvements depuis un <strong>ESP32<\/strong>. Comme la base de donn\u00e9es est utilisable pour plusieurs sortes d\u2019\u00e9v\u00e9nements, il serait possible d&#8217;utiliser le m\u00eame port en faisant les corrections n\u00e9cessaire, et par exemple coder l&#8217;entr\u00e9e <strong>\/passage<\/strong> dans un script Flask unique (voir le sketch Arduino <strong>esp32passage.ino<\/strong> et  le script Python <strong>getevent2.py<\/strong> ).      <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"postemail\">Envoi par courriel des temp\u00e9ratures extr\u00eames d&#8217;une journ\u00e9e<\/h2>\n\n\n\n<p>Cette derni\u00e8re partie va extraire de la base de donn\u00e9es <strong>SQLite <\/strong>les temp\u00e9ratures d&#8217;une journ\u00e9es, depuis minuit, et re\u00e7ues de notre dernier <strong>ESP8266<\/strong>. Nous allons &#8220;calculer&#8221; les deux temp\u00e9ratures extr\u00eames, le minimum et le maximum, pour les pr\u00e9senter dans une page Web toute simple avec un bouton optionnel pour envoyer un courriel.<br><br>Pour tester cette partie, je l&#8217;ai faite enti\u00e8rement sous Eclipse depuis un PC Windows pour me faciliter la t\u00e2che et apr\u00e8s avoir repris avec <strong>WinScp <\/strong>mon fichier <strong>SQLite_Python.db<\/strong> d\u00e9j\u00e0 bien peupl\u00e9 \u00e0 la suite de mes tests.<\/p>\n\n\n\n<p>Il est tout \u00e0 fait possible de d\u00e9velopper cette partie sous Windows avec Notepad++ et une console CMD, voire directement sur le Raspberry Pi. Mais si on d\u00e9sire l&#8217;\u00e9tendre un peu, y ajouter du code Python ou SQLite, cela deviendrait vite un casse t\u00eate. De plus le DB Browser for SQLite sous Windows nous permettrait de v\u00e9rifier des fonctions SQL comme SELECT min(value) FROM events et ceci en utilisant l&#8217;onglet Ex\u00e9cuter le SQL et sa fen\u00eatre, avant de le coder en Python.       <\/p>\n\n\n\n<p>Le code, raisonnablement simplifi\u00e9, sans trop de fioritures Flask et Python, se trouve dans le fichier <strong>min_max_sqlite_email_get.py<\/strong>: <br><\/p>\n\n\n\n<pre style=\"padding: 8.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; border-radius: 4px; margin-top: 0px; margin-bottom: 9px; line-height: 18px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; background-color: #CCFFCC; border: 1px solid rgba(0, 0, 0, 0.15);\"><span style=\"font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;\"><span style=\"font-size: 16px; white-space: pre-wrap;\">#Test with \"http:\/\/127.0.0.1:8080\"\n\nfrom flask import Flask, request\nfrom datetime import datetime\nimport sqlite3\nimport smtplib, ssl\n\napp = Flask(__name__)\n\ndef getMinMax():\n    now = datetime.now()\n    da = now.strftime(\"%d\/%m\/%Y\")  #Today\n    \n    sqliteConnection = sqlite3.connect('SQLite_Python.db')\n    cursor = sqliteConnection.cursor()\n    cursor.execute(\"SELECT min(value) FROM events \\\nwhere nameevent = 'temperature' AND thedate = '\" + da +\"'\") \n    rows1 = cursor.fetchall()\n\n    cursor.execute(\"SELECT max(value) FROM events \\\nwhere nameevent = 'temperature' AND thedate = '\" + da +\"'\") \n    rows2 = cursor.fetchall()\n        \n    return rows1[0][0], rows2[0][0], da\n\n@app.route(\"\/\")\ndef hello():     \n    lemin, lemax, ladate = getMinMax() # Assign tuple \n\n    return '&lt;H3&gt;Minimum and maximum: ' + str(lemin) + ' and ' + \\\nstr(lemax) + ' degrees&lt;\/H3&gt;&lt;P&gt;' \\\n'&lt;H4&gt;For date: ' + ladate + '&lt;P&gt;Maybe for sending send to:  \\\n&lt;form action=\"\/sendmail\" method=\"GET\"&gt;&lt;input name=\"emailadd\"&gt;' + \\\n'&lt;input type=\"submit\" value=\"Email address\"&gt;' + \\\n'&lt;input type=\"hidden\" name=\"ladate\" value=\"' + str(ladate) + '\"&gt;' + \\\n'&lt;input type=\"hidden\" name=\"mint\" value=\"' + str(lemin) + '\"&gt;' + \\\n'&lt;input type=\"hidden\" name=\"maxt\" value=\"' + str(lemax) + '\"&gt;' + \\\n'&lt;\/form&gt;&lt;\/H4&gt;'\n\n@app.route(\"\/sendmail\")\ndef sendmail():\n    port = 587  # For starttls\n    smtp_server = \"smtp.gmail.com\"\n    sender_email = \"....\"\n    password = \"....\"\n    \n    receiver_email = request.args.get('emailadd') \n    if len(receiver_email) == 0:\n      return \"No email address\"\n    if receiver_email.find(\"@\") == -1:\n      return \"Not an email address\"\n      \n    da = request.args.get('ladate')\n    mint = request.args.get('mint')\n    maxt = request.args.get('maxt') \n\n    message = \"\"\"\\\nSubject: Temperatures minimum and maximum for the \"\"\" + str(da) + \"\"\"\\\n\nMinimum \"\"\" + str(mint) + \"\"\"\\\n\\nMaximum \"\"\" + str(maxt) + \"\"\"\\\n\\nThis message is sent from Flask Python min_max_sqlite_email_get.py\"\"\"\n\n    context = ssl.create_default_context()\n    with smtplib.SMTP(smtp_server, port) as server:\n      server.starttls(context=context)\n      server.login(sender_email, password)\n      server.sendmail(sender_email, receiver_email, message)\n    \n    return \"Email to \" + request.args.get('emailadd', '') + ' with ' + request.args.get('mint', '') + ' and ' + request.args.get('maxt', '')\n\nif __name__ == \"__main__\":\n    app.run(host='0.0.0.0', port=8080)\n<\/span><\/span><\/pre>\n\n\n\n<p>Un des c\u0153urs de ce code est \u00e9videmment la fonction <strong>getMinMax()<\/strong> retournant un Tuple avec les temp\u00e9ratures minimale et  maximale de la journ\u00e9e. C&#8217;est pour la journ\u00e9e au moment de la demande. S&#8217;il est 14:00, nous recevrons donc les deux temp\u00e9ratures depuis minuit. Si nous voulions d&#8217;autres extr\u00eames, pour par exemple une journ\u00e9e enti\u00e8re ou sur 24 heures, le code devrait \u00eatre s\u00e9rieusement \u00e9tendu. Ici on fait presque dans le plus simple possible. Ce qui est int\u00e9ressant ici ce sont le m\u00e9thodes <strong>min(value)<\/strong> et <strong>max(value)<\/strong>, appel\u00e9 souvent aggregate, qui nous retournent les extr\u00eames d&#8217;une colonne d&#8217;une requ\u00eate o\u00f9 nous avons d\u00e9j\u00e0 s\u00e9lectionn\u00e9 un type d\u2019\u00e9v\u00e9nement particulier et une date fixe. La date est gard\u00e9e pour \u00eatre plus tard pass\u00e9e au document html du script Flask.<br><br>Les deux <strong>select <\/strong>ne contiennent aucune r\u00e9f\u00e9rence \u00e0 la source de la temp\u00e9rature. Il faudrait y ajouter un <strong>where <\/strong>sur le champ <strong>namesource<\/strong>. Ce serait le cas si nous d\u00e9sirions s\u00e9lectionner la pi\u00e8ce o\u00f9 la temp\u00e9rature est mesur\u00e9e. Le code se compliquerait alors.<br><br>Vu la complexit\u00e9 du code et les possibilit\u00e9s d&#8217;extension, c&#8217;est un peu difficile de s&#8217;imaginer de d\u00e9velopper cette application Flask sans un outil \u00e9labor\u00e9, par exemple avec PyDev sous Eclipse.<\/p>\n\n\n\n<p>Pour l&#8217;envoi d&#8217;un courriel, il faudra identifier les information du serveur <strong>SMTP <\/strong>il faudra conna\u00eetre ces informations. Il est possible de les retrouver, par exemple pour les utilisateur de <strong>Thunderbird<\/strong>, sous <strong>Outil <\/strong>\/ <strong>Param\u00e8tres des comptes<\/strong> et tout en bas<strong> Serveur sortants SMTP<\/strong>. <\/p>\n\n\n\n<p>Pour l&#8217;envoi d&#8217;un courriel, il faudra identifier les information du serveur <strong>SMTP<\/strong>, il faudra conna\u00eetre ces informations. J\u2019ai utiliser moi-m\u00eame mon compte Gmail avec le port <strong>587 <\/strong>(<strong>starttls<\/strong>). Il est possible de les retrouver, par exemple pour les utilisateur de Thunderbird, sous Outil \/ Param\u00e8tres des comptes et tout en bas Serveur sortants <strong>SMTP<\/strong>.<br><br>Je ne donnerai pas plus de d\u00e9tails, car de nombreux sites Web nous expliquent comment g\u00e9n\u00e9rer des emails en Python voire y joindre des attachements (le mot cl\u00e9 \u00e0 utiliser lors des recherches sera MIMEMultipart).<\/p>\n\n\n\n<p>Un test depuis PyDev sous Eclipse se pr\u00e9senterait ainsi:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"725\" height=\"339\" src=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/10\/MinMax.jpg\" alt=\"\" class=\"wp-image-1282\" srcset=\"https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/10\/MinMax.jpg 725w, https:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2019\/10\/MinMax-300x140.jpg 300w\" sizes=\"(max-width: 725px) 100vw, 725px\" \/><\/figure>\n\n\n\n<p>L&#8217;onglet <strong>min_max_sqlite_email_get<\/strong> contient le code de notre script Python Flask avec la fameuse ligne comment\u00e9e <strong>Test with &#8220;http:\/\/127.0.0.1:8080&#8221;<\/strong> nous permettant d&#8217;examiner le r\u00e9sultat, comme expliquer pr\u00e9c\u00e9demment. Si nous n&#8217;avons pas de temp\u00e9rature pour ce jour, nous verrions alors deux <strong>None <\/strong>\u00e0 la place de ces deux temp\u00e9ratures.<br><br>Le code reste simple, et nous pourrions y ajouter plus de cas d&#8217;erreurs et ne pas envoyer de courriel dans ces cas. Le bouton <strong>Email address<\/strong> nous permettra d&#8217;envoyer un courriel basique \u00e0 l&#8217;adresse indiqu\u00e9e o\u00f9 le code ne v\u00e9rifie que les cas o\u00f9 le champ est vide ou ne contient pas de caract\u00e8re @.<\/p>\n\n\n\n<p>Apr\u00e8s avoir programm\u00e9 et test\u00e9 <strong>min_max_sqlite_email_get.py<\/strong> sur un PC Windows nous pourrions le transf\u00e9rer avec WinSCP sur le Raspberry Pi, dans le r\u00e9pertoire flaskeur, afin de l&#8217;ex\u00e9cuter avec <strong>python3 min_max_sqlite_email_get.py<\/strong>. <br>Un test depuis le PC avec http:\/\/192.168.1.143:8080\/ dans notre explorateur Web favori, si notre Raspberry Pi poss\u00e8de cette adresse IP, \u00e9videmment.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"postemail\">Et la suite \u2026.<\/h2>\n\n\n\n<p>Plein d&#8217;exercices sont possibles ici, il y a tellement de sujets abord\u00e9s ici. Comme nous collectionnons, dans une base de donn\u00e9es, des temp\u00e9ratures ou des passages de personnes ou d&#8217;animaux dans une pi\u00e8ce, nous pourrions alors nous pencher sur des statistiques, des moyennes, et pourquoi pas la g\u00e9n\u00e9ration de graphiques sur une page Web voire un document envoy\u00e9 par courriel et g\u00e9n\u00e9r\u00e9 par Excel.<br><br>Des id\u00e9es de cours d\u2019introduction au langage Python, au Raspberry Pi, aux ESP32 ou ESP8266 sont des sujets qui me viendraient \u00e0 l&#8217;esprit, en terminant cet article qui m&#8217;a pris un peu plus de 2 mois \u00e0 vrai dire et m&#8217;a apporter beaucoup de satisfaction! J&#8217;avais \u00e9videmment d\u00e9j\u00e0 tout le mat\u00e9riel, et beaucoup de code r\u00e9utilisable, sauf la partie Flask elle-m\u00eame, vraiment nouvelle pour moi.<\/p>\n\n\n\n<p> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cet article a \u00e9t\u00e9 soumis \u00e0 la r\u00e9daction de developpez.com&nbsp;et a \u00e9t\u00e9 publi\u00e9 en mars 2020. De nombreuses adaptations et suggestions des correcteurs y ont&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"ngg_post_thumbnail":0,"footnotes":""},"categories":[7],"tags":[9],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Python Web Flask et SQLite pour le Raspberry Pi - Jean-Bernard Boichat<\/title>\n<meta name=\"description\" content=\"Site de Jean-Bernard Boichat consacr\u00e9 principalement \u00e0 Wordpress, Elementor, l&#039;impression 3D, l&#039;\u00e9lectricit\u00e9, les installations photovolta\u00efques et la voiture \u00e9lectrique.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Python Web Flask et SQLite pour le Raspberry Pi - Jean-Bernard Boichat\" \/>\n<meta property=\"og:description\" content=\"Site de Jean-Bernard Boichat consacr\u00e9 principalement \u00e0 Wordpress, Elementor, l&#039;impression 3D, l&#039;\u00e9lectricit\u00e9, les installations photovolta\u00efques et la voiture \u00e9lectrique.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/\" \/>\n<meta property=\"og:site_name\" content=\"Jean-Bernard Boichat\" \/>\n<meta property=\"article:published_time\" content=\"2019-10-09T14:11:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-10-11T08:19:14+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2018\/10\/RaspberryPi1.jpg\" \/>\n<meta name=\"author\" content=\"Jean-Bernard Boichat\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jean-Bernard Boichat\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"55 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/\"},\"author\":{\"name\":\"Jean-Bernard Boichat\",\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/fe6328cc5b74b8a6e8d841285a928751\"},\"headline\":\"Python Web Flask et SQLite pour le Raspberry Pi\",\"datePublished\":\"2019-10-09T14:11:07+00:00\",\"dateModified\":\"2025-10-11T08:19:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/\"},\"wordCount\":9258,\"publisher\":{\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/fe6328cc5b74b8a6e8d841285a928751\"},\"keywords\":[\"Python Flask Raspberry Pi ESP8266 ESP32 SQLite\"],\"articleSection\":[\"Python Flask\"],\"inLanguage\":\"fr-FR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/\",\"url\":\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/\",\"name\":\"Python Web Flask et SQLite pour le Raspberry Pi - Jean-Bernard Boichat\",\"isPartOf\":{\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/#website\"},\"datePublished\":\"2019-10-09T14:11:07+00:00\",\"dateModified\":\"2025-10-11T08:19:14+00:00\",\"description\":\"Site de Jean-Bernard Boichat consacr\u00e9 principalement \u00e0 Wordpress, Elementor, l'impression 3D, l'\u00e9lectricit\u00e9, les installations photovolta\u00efques et la voiture \u00e9lectrique.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.boichat.ch\/wordpress\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Python Web Flask et SQLite pour le Raspberry Pi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/#website\",\"url\":\"https:\/\/www.boichat.ch\/wordpress\/\",\"name\":\"Jean-Bernard Boichat\",\"description\":\"Mon site WordPress\",\"publisher\":{\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/fe6328cc5b74b8a6e8d841285a928751\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.boichat.ch\/wordpress\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"fr-FR\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/fe6328cc5b74b8a6e8d841285a928751\",\"name\":\"Jean-Bernard Boichat\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/862886ce35a52b9d13595e18ac3c3ea5?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/862886ce35a52b9d13595e18ac3c3ea5?s=96&d=mm&r=g\",\"caption\":\"Jean-Bernard Boichat\"},\"logo\":{\"@id\":\"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Python Web Flask et SQLite pour le Raspberry Pi - Jean-Bernard Boichat","description":"Site de Jean-Bernard Boichat consacr\u00e9 principalement \u00e0 Wordpress, Elementor, l'impression 3D, l'\u00e9lectricit\u00e9, les installations photovolta\u00efques et la voiture \u00e9lectrique.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/","og_locale":"fr_FR","og_type":"article","og_title":"Python Web Flask et SQLite pour le Raspberry Pi - Jean-Bernard Boichat","og_description":"Site de Jean-Bernard Boichat consacr\u00e9 principalement \u00e0 Wordpress, Elementor, l'impression 3D, l'\u00e9lectricit\u00e9, les installations photovolta\u00efques et la voiture \u00e9lectrique.","og_url":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/","og_site_name":"Jean-Bernard Boichat","article_published_time":"2019-10-09T14:11:07+00:00","article_modified_time":"2025-10-11T08:19:14+00:00","og_image":[{"url":"http:\/\/www.boichat.ch\/wordpress\/wp-content\/uploads\/2018\/10\/RaspberryPi1.jpg"}],"author":"Jean-Bernard Boichat","twitter_card":"summary_large_image","twitter_misc":{"\u00c9crit par":"Jean-Bernard Boichat","Dur\u00e9e de lecture estim\u00e9e":"55 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/#article","isPartOf":{"@id":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/"},"author":{"name":"Jean-Bernard Boichat","@id":"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/fe6328cc5b74b8a6e8d841285a928751"},"headline":"Python Web Flask et SQLite pour le Raspberry Pi","datePublished":"2019-10-09T14:11:07+00:00","dateModified":"2025-10-11T08:19:14+00:00","mainEntityOfPage":{"@id":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/"},"wordCount":9258,"publisher":{"@id":"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/fe6328cc5b74b8a6e8d841285a928751"},"keywords":["Python Flask Raspberry Pi ESP8266 ESP32 SQLite"],"articleSection":["Python Flask"],"inLanguage":"fr-FR"},{"@type":"WebPage","@id":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/","url":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/","name":"Python Web Flask et SQLite pour le Raspberry Pi - Jean-Bernard Boichat","isPartOf":{"@id":"https:\/\/www.boichat.ch\/wordpress\/#website"},"datePublished":"2019-10-09T14:11:07+00:00","dateModified":"2025-10-11T08:19:14+00:00","description":"Site de Jean-Bernard Boichat consacr\u00e9 principalement \u00e0 Wordpress, Elementor, l'impression 3D, l'\u00e9lectricit\u00e9, les installations photovolta\u00efques et la voiture \u00e9lectrique.","breadcrumb":{"@id":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.boichat.ch\/wordpress\/2019\/10\/09\/python-flask-raspberry-pi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.boichat.ch\/wordpress\/"},{"@type":"ListItem","position":2,"name":"Python Web Flask et SQLite pour le Raspberry Pi"}]},{"@type":"WebSite","@id":"https:\/\/www.boichat.ch\/wordpress\/#website","url":"https:\/\/www.boichat.ch\/wordpress\/","name":"Jean-Bernard Boichat","description":"Mon site WordPress","publisher":{"@id":"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/fe6328cc5b74b8a6e8d841285a928751"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.boichat.ch\/wordpress\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"fr-FR"},{"@type":["Person","Organization"],"@id":"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/fe6328cc5b74b8a6e8d841285a928751","name":"Jean-Bernard Boichat","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/862886ce35a52b9d13595e18ac3c3ea5?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/862886ce35a52b9d13595e18ac3c3ea5?s=96&d=mm&r=g","caption":"Jean-Bernard Boichat"},"logo":{"@id":"https:\/\/www.boichat.ch\/wordpress\/#\/schema\/person\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/posts\/406"}],"collection":[{"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/comments?post=406"}],"version-history":[{"count":0,"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/posts\/406\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/media?parent=406"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/categories?post=406"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.boichat.ch\/wordpress\/wp-json\/wp\/v2\/tags?post=406"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}