Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Des données au graphique :un parcours Web avec Flask et SQLite

Capturer des données réelles (RPi/DHT22), les enregistrer dans une base de données (SQLite), créer des graphiques (Matplotlib) et les présenter sur une page web (Flask).

Introduction :des données au graphique. un Web Jorney avec Flask et SQLite

Dans mon tutoriel précédent, Python WebServer With Flask et Raspberry Pi, nous avons appris à interagir avec le monde physique, via une page Web frontale, construite avec Flask. Ainsi, la prochaine étape naturelle consiste à collecter des données du monde réel, en les mettant à notre disposition sur une page Web. Très simple! Mais que se passera-t-il si nous voulons savoir quelle était la situation la veille, par exemple ? Ou faire une sorte d'analyse avec ces données ? Dans ces cas, nous devons également avoir les données stockées dans une base de données.

Bref, sur ce nouveau tutoriel, nous allons :

Capturez des données réelles (température de l'air et humidité relative) à l'aide d'un capteur DHT22 ; chargez ces données sur une base de données locale , construit avec SQLite ; Créer des graphiques avec données historiques en utilisant Matplotlib ; Afficher les données avec des « gages » animés, créés avec JustGage ; Rendre tout disponible en ligne via un serveur Web local créé avec  Python et Flacon ;

Le schéma bloc nous donne une idée de l'ensemble du projet :

Étape 1 :BoM - Nomenclature

Étape 2 :Installation de SQLite

OK, l'idée générale sera de collecter des données à partir d'un capteur et de les stocker dans une base de données.

Mais quel « moteur » de base de données faut-il utiliser ?

Il existe de nombreuses options sur le marché et les 2 plus utilisées avec Raspberry Pi et les capteurs sont probablement MySQL et SQLite. MySQL est très connu mais un peu "lourd" pour une utilisation sur des projets simples basés sur Raspberry (d'ailleurs il appartient à Oracle !). SQLite est probablement le choix le plus approprié. Parce qu'il est sans serveur, léger, open source et prend en charge la plupart des codes SQL (sa licence est « Domaine public »). Une autre chose pratique est que SQLite stocke les données dans un seul fichier qui peut être stocké n'importe où.

Mais qu'est-ce que SQLite ?

SQLite est un système de gestion de base de données relationnelle contenu dans une bibliothèque de programmation C. Contrairement à de nombreux autres systèmes de gestion de bases de données, SQLite n'est pas un moteur de base de données client-serveur. Il est plutôt intégré au programme final.

SQLite est un domaine public populaire choix comme logiciel de base de données intégré pour le stockage local/client dans les logiciels d'application tels que les navigateurs Web. C'est sans doute le moteur de base de données le plus largement déployé, car il est utilisé aujourd'hui par plusieurs navigateurs, systèmes d'exploitation et systèmes embarqués répandus (tels que les téléphones portables), entre autres. SQLite a des liaisons avec de nombreux langages de programmation comme Python, celui utilisé sur notre projet.

(En savoir plus sur Wikipédia)

Nous n'entrerons pas dans trop de détails ici, mais la documentation complète de SQLite se trouve sur ce lien : https://www.sqlite.org/docs.html

Ainsi soit-il! Installons SQLite sur notre Pi

Installation :

Suivez les étapes ci-dessous pour créer une base de données.

1. Installez SQLite sur Raspberry Pi à l'aide de la commande :

sudo apt-get install sqlite3 

2. Créez un répertoire pour développer le projet :

mkdir Sensors_Database 

3. Accédez à ce répertoire :

cd mkdir Sensors_Database/ 

3. Donnez un nom et créez une base de données comme databaseName.db (dans mon cas "sensorsData.db") :

sqlite3 sensorData.db 

Un "shell" apparaîtra, où vous pouvez entrer avec des commandes SQLite. Nous y reviendrons plus tard.

sqlite> 

Les commandes commencent par un ".", comme ".help", ".quit", etc.

4. Quittez le shell pour revenir au Terminal :

sqlite> .quit 

L'écran d'impression du terminal ci-dessus montre ce qui a été expliqué.

Le "sqlite>" ci-dessus ne sert qu'à illustrer comment le shell SQLite apparaîtra. Vous n'avez pas besoin de le taper. Il apparaîtra automatiquement.

Étape 3 :Créer et remplir une table

Afin d'enregistrer les données mesurées par le capteur DHT dans la base de données, nous devons créer un tableau  (une base de données peut contenir plusieurs tables). Notre tableau s'appellera "DHT_data" et comportera 3 colonnes, dans lesquelles nous enregistrerons nos données collectées :Date et Heure (nom de la colonne : timestamp ), Température (nom de la colonne : temp ) et l'humidité (nom de la colonne : hum ).

Créer un tableau :

Pour créer un tableau, vous pouvez le faire :

1. Utilisation de Shell :

Ouvrez la base de données qui a été créée à la dernière étape :

sqlite3 sensorData.db 

Et en entrant avec des instructions SQL :

sqlite> BEGIN;sqlite> CREATE TABLE DHT_data (timestamp DATETIME, temp NUMERIC, hum NUMERIC);sqlite> COMMIT; 

Toutes les instructions SQL doivent se terminer par « ; ». De plus, ces déclarations sont généralement écrites en majuscules. Ce n'est pas obligatoire, mais une bonne pratique.

2. Utilisation de Python

importer sqlite3 en tant que liteimport syscon =lite.connect('sensorsData.db')avec con :cur =con.cursor() cur.execute("DROP TABLE IF EXISTS DHT_data") cur.execute("CREATE TABLE DHT_data(timestamp DATETIME, temp NUMERIC, hum NUMERIC)") 

Ouvrez le code ci-dessus depuis mon GitHub : createTableDHT.py

Exécutez-le sur votre terminal :

python3 createTableDHT.py 

Quelle que soit la méthode utilisée, la table doit être créée. Vous pouvez le vérifier sur SQLite Shell en utilisant la commande ".table". Ouvrez le shell de la base de données :

sqlite3> sensorData.db 

Dans le shell, une fois que vous utilisez le .table commande, les noms des tables créées apparaîtront (dans notre cas, il n'y en aura qu'un :"DHT_table". Quittez le shell après, en utilisant le .quit  commande.

sqlite> .tableDHT_datasqlite> .quit 

Insérer des données dans un tableau :

Entrons dans notre base de données 3 ensembles de données, où chaque ensemble aura 3 composants chacun :(timestamp, temp et hum). Le composant horodatage sera réel et extrait du système, à l'aide de la fonction intégrée « now » et temp et hum sont des données factices en oC et % respectivement.

Remarque que l'heure est en "UTC", ce qui est bien car vous n'avez pas à vous soucier des problèmes liés à l'heure d'été et à d'autres questions. Si vous souhaitez afficher la date en heure localisée, convertissez-la simplement dans le fuseau horaire approprié par la suite.

De la même manière que pour la création de table, vous pouvez insérer des données manuellement via SQLite shell ou via Python. Au niveau du shell, vous le feriez, données par données en utilisant des instructions SQL comme celle-ci (Pour notre exemple, vous le ferez 3 fois) :

sqlite> INSÉRER DANS LES VALEURS DHT_data(datetime('now'), 20.5, 30); 

Et en Python, vous feriez la même chose mais d'un coup :

importer sqlite3 en tant que liteimport syscon =lite.connect('sensorsData.db')avec con :cur =con.cursor() cur.execute("INSERT INTO DHT_data VALUES (datetime('now'), 20.5, 30)") cur.execute("INSERT INTO DHT_data VALUES(datetime('now'), 25.8, 40)") cur.execute("INSERT INTO DHT_data VALUES(datetime(' maintenant'), 30.3, 50)") 

Ouvrez le code ci-dessus depuis mon GitHub : insertTableDHT.py

Exécutez-le sur le terminal Pi :

python3 insertTableDHT.py 

Pour confirmer que le code ci-dessus a fonctionné, vous pouvez vérifier les données de la table via le shell, avec l'instruction SQL :

sqlite> SELECT * FROM DHT_DATA ; 

L'écran d'impression du terminal ci-dessus montre comment les lignes du tableau apparaîtront.

Étape 4 :Insertion et vérification des données avec Python

Pour commencer, faisons la même chose que nous avons fait auparavant (saisir et récupérer des données), mais en faisant les deux avec python et en imprimant également les données sur le terminal :

import sqlite3import sysconn=sqlite3.connect('sensorsData.db')curs=conn.cursor()# fonction pour insérer des données sur une tabledef add_data (temp, hum) :curs.execute("INSERT INTO DHT_data values(datetime('now'), (?), (?))", (temp, hum)) conn.commit()# appelle la fonction pour insérer dataadd_data (20.5, 30 )add_data (25.8, 40)add_data (30.3, 50)# print database contentprint ("\nEntire database content:\n")for row in curs.execute("SELECT * FROM DHT_data"):print (row)# ferme le base de données après useconn.close() 

Ouvrez le code ci-dessus depuis mon GitHub : insertDataTableDHT.py et exécutez-le sur votre terminal :

python3 insertDataTableDHT.py 

L'écran d'impression du terminal ci-dessus montre le résultat.

Étape 5 : Capteur de température et d'humidité DHT22

Jusqu'à présent, nous avons créé une table dans notre base de données, où nous enregistrerons toutes les données qu'un capteur lira. Nous y sommes également entrés avec quelques données factices. Il est maintenant temps d'utiliser des données réelles à enregistrer dans notre table, la température de l'air et l'humidité relative. Pour cela, nous utiliserons l'ancien et le bon DHTxx (DHT11 ou DHT22). Le site ADAFRUIT fournit d'excellentes informations sur ces capteurs. Ci-dessous, quelques informations récupérées à partir de là :

Aperçu

Les capteurs de température et d'humidité DHT à faible coût sont très basiques et lents, mais sont parfaits pour les amateurs qui souhaitent enregistrer des données de base. Les capteurs DHT sont constitués de deux parties, un capteur d'humidité capacitif et une thermistance. Il y a aussi une puce très basique à l'intérieur qui effectue une conversion analogique-numérique et crache un signal numérique avec la température et l'humidité. Le signal numérique est assez facile à lire à l'aide de n'importe quel microcontrôleur.

DHT11 contre DHT22

Nous avons deux versions du capteur DHT, elles se ressemblent un peu et ont le même brochage, mais ont des caractéristiques différentes. Voici les spécifications :

DHT11 (généralement bleu)

Bon pour les lectures d'humidité de 20 à 80 % avec une précision de 5 % Bon pour les lectures de température de 0 à 50 °C Précision de ± 2 °C Pas plus de 1 Hz de fréquence d'échantillonnage (une fois par seconde)

DHT22 (généralement blanc)

Bon pour les lectures d'humidité de 0 à 100 % avec une précision de 2 à 5 % Bon pour les lectures de température de -40 à 125 °C Précision de ±0,5 °C Taux d'échantillonnage pas plus de 0,5 Hz (une fois toutes les 2 secondes)

Comme vous pouvez le voir, le DHT22 est un peu plus précis et bon sur une plage légèrement plus large. Les deux utilisent une seule broche numérique et sont « lents » en ce sens que vous ne pouvez pas les interroger plus d'une fois par seconde (DHT11) ou deux (DHT22).

Les deux capteurs fonctionneront correctement pour que les informations intérieures soient stockées dans notre base de données.

Le DHTxx a 4 broches (face au capteur, la broche 1 est la plus à gauche) :

Nous utiliserons un DHT22 dans notre projet.

Une fois que vous utiliserez habituellement le capteur sur des distances inférieures à 20 m, une résistance de 4K7 ohms doit être connectée entre les broches Data et VCC. La broche de données de sortie DHT22 sera connectée au Raspberry GPIO 16.

Vérifiez le schéma électrique ci-dessus reliant le capteur aux broches RPi comme ci-dessous :

N'oubliez pas d'installer la résistance 4K7 ohms entre les broches Vcc et Data. Une fois le capteur connecté, il faut aussi installer sa librairie sur notre RPi. Nous le ferons à l'étape suivante.

Étape 6 :Installation de la bibliothèque DHT

Sur votre Raspberry, à partir de /home, allez dans /Documents :

Cd Documents  

Créez un répertoire pour installer la bibliothèque et accédez-y :

mkdir DHT22_Sensorcd DHT22_Sensor 

Sur votre navigateur, accédez à Adafruit GITHub : https://github.com/adafruit/Adafruit_Python_DHT

Téléchargez la bibliothèque en cliquant sur le lien de téléchargement zip à droite et décompressez l'archive sur votre dossier Raspberry Pi récemment créé. Allez ensuite dans le répertoire de la bibliothèque (sous-dossier qui est automatiquement créé lorsque vous décompressez le fichier), et exécutez la commande :

sudo python3 setup.py install 

Ouvrez un programme de test (DHT22_test.py) depuis mon GITHUB :

import Adafruit_DHTDHT22Sensor =Adafruit_DHT.DHT22DHTpin =16humidité, température =Adafruit_DHT.read_retry(DHT22Sensor, DHTpin) si l'humidité n'est pas Aucune et la température n'est pas Aucune :print('Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temperature, humidité))else :print('Échec de la lecture. Réessayez !') 

Exécutez le programme avec la commande :

python3 DHT22_test.py 

L'écran d'impression du terminal ci-dessus montre le résultat.

Étape 7 :Capturer des données réelles

Maintenant que nous avons les deux, le capteur et notre base de données tous installés et configurés, il est temps de lire et d'enregistrer les données réelles.

Pour cela, nous utiliserons le code :

import timeimport sqlite3import Adafruit_DHTdbname='sensorsData.db'sampleFreq =2 # time in seconds# get data from DHT sensordef getDHTdata():DHT22Sensor =Adafruit_DHT.DHT22 DHTpin =16 hum, temp =Adafruit_DHT.read_retry(DHT22Sensor, DHTpin) si hum n'est pas Aucun et que temp n'est pas Aucun :hum =round(hum) temp =round(temp, 1) logData (temp, hum)# enregistre les données du capteur sur databasedef logData (temp, hum):conn=sqlite3.connect(dbname) curs=conn.cursor() curs.execute("INSERT INTO DHT_data values(datetime('now'), (?), (?))", (temp , hum)) conn.commit() conn.close()# afficher la base de données datadef displayData() :conn=sqlite3.connect(dbname) curs=conn.cursor() print ("\nContenu entier de la base de données :\n") pour ligne dans curs.execute("SELECT * FROM DHT_data") :print (ligne) conn.close()# main functiondef main() :pour i dans la plage (0,3) :getDHTdata() time.sleep(sampleFreq) displayData ()# Exécuter le programme main() 

Ouvrez le fichier ci-dessus depuis mon GitHub : appDHT.pyet exécutez-le sur votre terminal :

python3 appDHT.py 

La fonction getDHTdata() capture 3 échantillons de capteur DHT, testez-les pour les erreurs et si OK, enregistrez les données sur la base de données à l'aide de la fonction logData (temp, hum) . La dernière partie du code appelle la fonction displayData() qui imprime tout le contenu de notre table sur Terminal.

L'écran d'impression ci-dessus montre le résultat. Observez que les 3 dernières lignes (lignes) sont les données réelles capturées avec ce programme et les 3 lignes précédentes étaient celles saisies manuellement auparavant.

En fait, appDHT.py n'est pas un bon nom. En général, « appSomething.py » est utilisé avec les scripts Python sur les serveurs web comme nous le verrons plus loin dans ce tutoriel. Mais bien sûr, vous pouvez l'utiliser ici.

Étape 8 :Capturer les données automatiquement

À ce stade, ce que nous devons mettre en œuvre est un mécanisme pour lire et insérer des données dans notre base de données automatiquement, notre « Logger ».

Ouvrir une nouvelle fenêtre de terminal et entrez avec le code Python ci-dessous :

import timeimport sqlite3import Adafruit_DHTdbname='sensorsData.db'sampleFreq =1*60 # time in seconds ==> Sample chaque 1 min# get data from DHT sensordef getDHTdata() :DHT22Sensor =Adafruit_DHT.DHT22 DHTpin =16 hum, temp =Adafruit_DHT.read_retry(DHT22Sensor, DHTpin) si hum n'est pas None et que temp n'est pas None :hum =round(hum) temp =round(temp, 1) return temp, hum # enregistre les données du capteur sur databasedef logData (temp, hum):conn=sqlite3.connect(dbname) curs=conn.cursor() curs.execute("INSERT INTO DHT_data values(datetime('now'), (?), ( ?))", (temp, hum)) conn.commit() conn.close()# main functiondef main():while True:temp, hum =getDHTdata() logData (temp, hum) time.sleep(sampleFreq) # ------------ Exécuter le programme main() 

Ou obtenez-le sur mon GitHub : logDHT.py. Exécutez-le sur le terminal :

python3 logDHT.py 

Ce que fait la fonction main() est :

Appelez la fonction getDHTdata() , qui renverra les données capturées par le capteur DHT22. Prenez ces données (température et humidité) et transmettez-les à une autre fonction : logData(temp, hum) qui les insère, avec la date et l'heure réelles, dans notre table. Et se met en veille, en attendant la prochaine heure programmée pour capturer les données (définie par sampleFreq , qui dans cet exemple est de 1 minute).

Laissez la fenêtre Terminal ouverte.

Jusqu'à ce que vous tuiez le programme avec [Ctr+z], par exemple, le programme capturera en continu les données, les alimentant dans notre base de données. Je l'ai laissé fonctionner pendant un certain temps sur une fréquence de 1 minute pour remplir la base de données plus rapidement, en changeant la fréquence après quelques heures à 10 minutes.

Il existe d'autres mécanismes beaucoup plus efficaces pour effectuer ce type de « logger automatique » que d'utiliser « time.sleep », mais le code ci-dessus fonctionnera correctement pour notre objectif ici. Quoi qu'il en soit, si vous souhaitez implémenter un meilleur « planificateur », vous pouvez utiliser Crontab , qui est un outil UNIX pratique pour planifier des tâches. Vous trouverez une bonne explication de ce qu'est Crontab dans ce didacticiel : « Planifier des tâches sur Linux à l'aide de Crontab », par Kevin van Zonneveld.

Étape 9 :Requêtes

Maintenant que notre base de données est alimentée automatiquement, nous devons trouver des moyens de travailler avec toutes ces données. Nous le faisons avec des requêtes !

Qu'est-ce qu'une requête ?

L'une des caractéristiques les plus importantes du travail avec le langage SQL sur les bases de données est la possibilité de créer des « requêtes de base de données ». En d'autres termes, les requêtes extraient les données d'une base de données en les formatant sous une forme lisible. Une requête doit être écrite en langage SQL , qui utilise un SELECT instruction pour sélectionner des données spécifiques.

Nous l'avons en fait utilisé de manière "large" sur la dernière étape :"SELECT * FROM DHT_data".

Exemples :

Créons des requêtes sur les données de la table que nous avons déjà créées. Pour cela, entrez avec le code ci-dessous :

import sqlite3conn=sqlite3.connect('sensorsData.db')curs=conn.cursor()maxTemp =27.6print ("\nContenu entier de la base de données :\n") pour la ligne dans curs.execute("SELECT * FROM DHT_data") :print (row)print ("\nEntrées de la base de données pour une valeur d'humidité spécifique :\n")pour la ligne dans curs.execute("SELECT * FROM DHT_data WHERE hum='29'") :print (row) print ("\nEntrées de la base de données où la température est supérieure à 30oC :\n") pour la ligne dans curs.execute("SELECT * FROM DHT_data WHERE temp>
30.0") :print (row) print ("\nEntrées de la base de données où la température est supérieure à x:\n") pour la ligne dans curs.execute("SELECT * FROM DHT_data WHERE temp>
(?)", (maxTemp,)):print (row)  

Ou récupérez-le sur mon GitHub : queryTableDHT.py et exécutez-le sur Terminal :

python3 queryTableDHT.py 

Vous pouvez voir le résultat sur l'écran d'impression du Terminal ci-dessus. Ce sont des exemples simples pour vous donner une idée concernant les requêtes. Prenez le temps de comprendre les instructions SQL dans le code ci-dessus.

Si vous souhaitez en savoir plus sur le langage SQL, une bonne source est le didacticiel SQL de W3School.

Étape 10 : dernières données saisies sur une table :

Une requête très importante est celle qui permet de récupérer les dernières données saisies (ou connecté) sur une table. On peut le faire directement sur le shell SQLite, avec la commande :

sqlite> SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1 ; 

Ou exécutez un simple code python comme ci-dessous :

import sqlite3conn =sqlite3.connect('sensorsData.db')curs=conn.cursor()print ("\nDernières données enregistrées dans la base de données :\n")pour ligne dans curs.execute("SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1") :print (ligne) 

Vous pouvez voir le résultat sur le premier écran d'impression Terminal ci-dessus.

Notez que le résultat apparaîtra sous la forme d'un « tuple de valeurs » :(« timestamp », temp, hum).

Le tuple a renvoyé le contenu de la dernière ligne de notre table, qui est formée de 3 éléments :

Ainsi, nous pouvons mieux travailler notre code, pour récupérer des données "propres" de la table, par exemple :

import sqlite3conn=sqlite3.connect('sensorsData.db')curs=conn.cursor()print ("\nDernières données brutes enregistrées dans la base de données :\n") pour la ligne dans curs.execute("SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1") :print (str(row[0])+" ==> Temp ="+str(row[1])+" Hum ="+str(ligne[2])) 

Ouvrez le fichier depuis mon GitHub : lastLogDataTableDHT.py et exécutez-le sur Terminal :

python3 lastLogDataTableDHT.py 

Vous pouvez voir le résultat sur l'écran d'impression du 2e terminal ci-dessus.

Étape 11 :Une interface Web pour la visualisation des données

Dans mon dernier tutoriel : Python WebServer With Flask and Raspberry Pi, nous avons appris à implémenter un serveur Web (à l'aide de Flask) pour capturer les données des capteurs et afficher leur état sur une page Web.

C'est ce que nous voulons également accomplir ici. La différence réside dans les données à envoyer à notre frontal, qui seront extraites d'une base de données et pas directement à partir des capteurs comme nous l'avons fait sur ce tutoriel.

Créer un environnement de serveur Web :

La première chose à faire est d'installer Flask sur votre Raspberry Pi. Si vous ne l'avez pas, rendez-vous sur le Terminal et saisissez :

sudo apt-get install python3-flask 

Le mieux lorsque vous démarrez un nouveau projet est de créer un dossier où organiser vos fichiers. Par exemple :

Depuis chez vous, rendez-vous dans notre répertoire de travail :

Cd Documents/Sensors_Database 

Créez un nouveau dossier, par exemple :

mkdir dhtWebServer 

La commande ci-dessus créera un dossier nommé "dhtWebServer", où nous enregistrerons nos scripts python :

/home/pi/Documents/Sensor_Database/rpiWebServer 

Maintenant, sur ce dossier, créons 2 sous-dossiers : static pour les fichiers CSS et éventuellement JavaScript et les modèles pour les fichiers HTML. Accédez à votre nouveau dossier créé :

cd dhtWebServer 

Et créez les 2 nouveaux sous-dossiers :

mkdir statique 

et

modèles mkdir 

Le répertoire final « arbre », ressemblera à :

├── Sensors_Database ├── sensorData.db ├── logDHT.py ├── dhtWebSensor ├── templates └── statique 

Nous laisserons notre base de données créée dans le répertoire /Sensor_Database, vous devrez donc connecter SQLite avec "../sensorsData.db".

D'ACCORD! Une fois notre environnement en place, assemblons les pièces et créons notre Application Python WebServer . Le schéma ci-dessus nous donne une idée de ce qu'il faut faire !

Étape 12 :L'application Python WebServer

À partir du dernier diagramme, créons un serveur Web python à l'aide de Flask. Je suggère  Geany comme IDE à utiliser,  une fois que vous pouvez travailler simultanément avec différents types de fichiers (.py, .html et .css).

Le code ci-dessous est le script python à utiliser sur notre premier serveur Web :

à partir de l'importation du flacon Flask, render_template, requestapp =Flask(__name__)import sqlite3# Récupérer les données de la base de donnéesdef getData() :conn=sqlite3.connect('../sensorsData .db') curs=conn.cursor() pour la ligne dans curs.execute("SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1"):time =str(row[0]) temp =row[1] hum =row [2] conn.close() return time, temp, hum# route principale @app.route("/")def index():time, temp, hum =getData() templateData ={ 'time':time, ' temp':temp, 'hum':hum } return render_template('index.html', **templateData)if __name__ =="__main__":app.run(host='0.0.0.0', port=80, debug=Faux) 

Vous pouvez obtenir le script python appDhtWebServer.py depuis mon GitHub. Le code ci-dessus fait :

Avec cette requête, la première chose à faire dans le code est de récupérer les données de la base de données à l'aide de la fonction time, temp, hum =getData(). Cette fonction est essentiellement la même requête qui était utilisée auparavant pour récupérer une donnée stockée dans la table. Avec les données en main, notre script retourne à la page Web (index.html ) : heuretemp  et hum en réponse à la demande précédente.

Voyons donc le index.html et style.css fichiers qui seront utilisés pour construire notre front-end :

index.html

  Données du capteur DHT     

Données du capteur DHT

TEMPÉRATURE ==> {{ tempLab }} oC

HUMIDITÉ (rel.) ==> { { humLab }} %


Dernière lecture des capteurs :{{ time }} ==> REFRESH


@2018 Développé par MJRoBot.org

Vous pouvez obtenir le fichier index.html depuis mon GitHub.

style.css

body{ background :blue ; Couleur jaune; padding:1%}.button { font:bold 15px Arial; texte-décoration :aucun; couleur d'arrière-plan :#EEEEEE ; couleur :#333333 ; rembourrage :2px 6px 2px 6px; border-top :1px solide #CCCCCC ; bordure droite : 1px solide #333333 ; bordure inférieure : 1px solide #333333 ; border-left :1px solide #CCCCCC;} 

Vous pouvez obtenir le fichier style.css depuis mon GitHub. Les fichiers doivent être placés dans votre répertoire comme ceci :

├── Sensors_Database ├── sensorData.db ├── logDHT.py ├── dhtWebSensor ├── appDhtWebSensor.py templates │ ├── index .html └── statique ├── style.css  

Maintenant, exécutez le script python sur le terminal :

sudo python3 appDhtWebServer.py 

Accédez à n'importe quel navigateur de votre réseau et saisissez http://YOUR_RPI_IP (par exemple, dans mon cas : http://10.01.27)

L'écran d'impression ci-dessus montre ce que vous devez voir. REMARQUE :Si vous n'êtes pas sûr de votre adresse IP RPi, exécutez sur votre terminal :

 ifconfig 

Dans la section wlan0:vous le trouverez. Dans mon cas :10.0.1.27

Étape 13 :Rendre notre Web Front-End Fancier !

Introduisons quelques jauges pour présenter les valeurs réelles de température et d'humidité d'une meilleure façon. Notez que notre script Python ne changera pas, mais l'utilisation de JustGage sur nos fichiers html/css améliorera considérablement la présentation des données.

Qu'est-ce que JustGage ?

JustGage est un plugin JavaScript pratique pour générer et animer des jauges agréables et propres. Il est basé sur la bibliothèque Raphaël pour le dessin vectoriel, il est donc complètement indépendant de la résolution et auto-ajustable, fonctionnant dans presque tous les navigateurs.

Installation :

justgage-1.2.2.zip

 Capteur de données DHT    

Données du capteur DHT


Dernière lecture des capteurs :{{ time }} ==> REFRESH


@2018 Développé par MJRoBot.org

Téléchargez depuis mon GitHub le fichier : index_gage.html, et renommez-le en index.html (n'oubliez pas de renommer le précédent avec un nom différent si vous souhaitez le conserver, par exemple, index_txt.html).

L'arborescence finale du répertoire devrait ressembler à ci-dessous :

├── Sensors_Database ├── sensorData.db ├── logDHT.py ├── dhtWebServer ├── appDhtWebServer.py ├── templates │ ├── index .html └── statique ├── style.css ├── justgage.js ├── raphael-2.1.4.min.js 

Appuyez sur [Crl-C] sur votre terminal pour quitter appDhtWebServer.py et redémarrez-le. Lorsque vous actualisez votre navigateur, vous devez voir l'écran d'impression ci-dessus.

Regardez les exemples de fichiers que vous avez téléchargés sur le site Web de JustGage. Essayez d'apporter des modifications à vos jauges. C'est très simple.

Étape 14 :Le processus complet

Le diagramme ci-dessus résume ce que nous avons accompli jusqu'à présent :2 scripts distincts exécutés en parallèle, effectuant leurs tâches indépendamment :

Capturer les données avec le capteur et les charger dans une base de données (logDHT.py ) Recherchez des données sur la base de données et présentez-les sur une interface Web (appDhtWebServer.py ).

En termes généraux, notre projet de capture de données, de les enregistrer sur une base de données et d'afficher ces données sur une page Web est terminé. Mais cela n'a aucun sens d'avoir une base de données avec des données historiques et de ne l'utiliser que pour les dernières données capturées. Nous devons jouer avec les données historiques et la chose la plus élémentaire à faire est de les présenter sur un graphique. Allons-y !

Étape 15 :Représentation graphique des données historiques

Une très bonne bibliothèque pour représenter graphiquement les données est Matplotlib that is a Python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms.

To install matplotlib , run the command below on your Terminal:

sudo apt-get install python3-matplotlib 

Before we start, let’s create a new environment, where we will save the new application to be developed: appDhtWebHist.py  and its correspondent index.html  and style.css

├── Sensors_Database ├── sensorsData.db ├── logDHT.py ├── dhtWebHist ├── appDhtWebHist.py ├── templates │ ├── index.html └── static ├── style.css  

Create the new 3 directories (dhtWebHist; /templates  and /static ) same as we did before and open from my GitHub the 3 files below:

1. appDhtWebHist.py

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvasfrom matplotlib.figure import Figureimport iofrom flask import Flask, render_template, send_file, make_response, requestapp =Flask(__name__)import sqlite3conn=sqlite3.connect('../sensorsData.db')curs=conn.cursor()# Retrieve LAST data from databasedef getLastData():for row in curs.execute("SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1"):time =str(row[0]) temp =row[1] hum =row[2] #conn.close() return time, temp, humdef getHistData (numSamples):curs.execute("SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT "+str(numSamples)) data =curs.fetchall() dates =[] temps =[] hums =[] for row in reversed(data):dates.append(row[0]) temps.append(row[1]) hums.append(row[2]) return dates, temps, humsdef maxRowsTable():for row in curs.execute("select COUNT(temp) from DHT_data"):maxNumberRows=row[0] return maxNumberRows# define and initialize global variablesglobal numSamplesnumSamples =maxRowsTable() if (numSamples> 101):numSamples =100# main [email protected]("/")def index():time, temp, hum =getLastData() templateData ={ 'time' :time, 'temp' :temp, 'hum' :hum, 'numSamples' :numSamples } return render_template('index.html', **templateData)@app.route('/', methods=['POST'])def my_form_post():global numSamples numSamples =int (request.form['numSamples']) numMaxSamples =maxRowsTable() if (numSamples> numMaxSamples):numSamples =(numMaxSamples-1) time, temp, hum =getLastData() templateData ={ 'time' :time, 'temp' :temp, 'hum' :hum, 'numSamples' :numSamples } return render_template('index.html', **templateData)@app.route('/plot/temp')def plot_temp():times, temps, hums =getHistData(numSamples) ys =temps fig =Figure() axis =fig.add_subplot(1, 1, 1) axis.set_title("Temperature [°C]") axis.set_xlabel("Samples") axis.grid(True) xs =range(numSamples) axis.plot(xs, ys) canvas =FigureCanvas(fig) output =io.BytesIO() canvas.print_png(output) response =make_response(output.getvalue()) response.mimetype ='image/png' return [email protected]('/plot/hum')def plot_hum():times, temps, hums =getHistData(numSamples) ys =hums fig =Figure() axis =fig.add_subplot(1, 1, 1) axis.set_title("Humidity [%]") axis.set_xlabel("Samples") axis.grid(True) xs =range(numSamples) axis.plot(xs, ys) canvas =FigureCanvas(fig) output =io.BytesIO() canvas.print_png(output) response =make_response(output.getvalue()) response.mimetype ='image/png' return responseif __name__ =="__main__":app.run(host='0.0.0.0', port=80, debug=False) 

A new function was created here: getHistData (numSamples) , that receives as a parameter the number of rows that should be taken from the database. Basically, it is very similar to getLastData(), where numSamples  was “1”. Of course, now we must “append” the return array for all required rows.

In fact, we could use only this last function for both tasks.

The number of samples is set by default as 100, at the beginning (if there are more them 100 rows into the database) and also received it as an input from the webpage, during normal operation. When we receive the number of samples to be retrieved, we must also check if it is lower than the maximum number of rows in the database (otherwise we will get an error). The function maxRowsTable() , returns this number.

With the historical data in hand: times, temps  and hums  that are arrays, we must build the graphs saving them as a .png ímage . Those images will be the return for the routes:

@app.route(‘/plot/temp’)  and @app.route(‘/plot/hum’).

The request for the images is done by index.html, by the IMG TAG.

2. index.html

  DHT Sensor data     

DHT Sensor Data

TEMPERATURE ==> {{ temp }} oC

HUMIDITY (Rel.) ==> {{ hum }} %


Last Sensors Reading:{{ time }} ==> REFRESH


HISTORICAL DATA

Enter number of samples to retrieve:


Image Placeholder Image Placeholder

@2018 Developed by MJRoBot.org

3. style.css

body{ background:blue; color:yellow; padding:1%}.button { font:bold 15px Arial; texte-décoration :aucun; background-color:#EEEEEE; color:#333333; padding:2px 6px 2px 6px; border-top:1px solid #CCCCCC; border-right:1px solid #333333; border-bottom:1px solid #333333; border-left:1px solid #CCCCCC;}img{ display:display:inline-block} 

The above print screen shows the result.

Step 16:Including Gage on History Webpage

If instead of text, you want also to include gages to display the actual data, you must have the 2 .js files that you have used before on /static and change the index.html file on /templates:

Below how the directory tree looks like:

├── Sensors_Database ├── sensorsData.db ├── logDHT.py ├── dhtWebHist ├── appDhtWebHist.py ├── templates │ ├── index.html └── static ├── style.css ├── justgage.js ├── raphael-2.1.4.min.js 

From my GitHub, open index_gage.html and rename it index.html. Replace the actual index.html (text version) and voilá! You will get a beautiful webpage, showing as gages the last captured data of temperature and humidity by the DHT22 and the historical graphs of those data.

Press[Crl-C] on your Terminal to Quit appDhtWebServer.py and just start it again. When you refresh your browser you must see the above print screen.

Step 17:Retrieving Data by Time Instead of Samples

So far we have build our graphics based on historical data, sending as a input parameter the numbers of samples to be retrieved from our database. Alternatively we could use as a parameter the number of past minutes that we want to show on a graph.

In order to do that, the first thing to know is the frequency of logged data on our database. Remember that this task is done for an independent program (in our case, logDHT.py ). One simple way to finfd this frequency is to retrieve the last 2 data logged on database and subtracting their correspondent timeStamp data:

in general terms: frequency =timeStamp(1) – timeStamp(0)

The function below does the work for us, using “datetime.striptime()”:

# Get sample frequency in minutesdef freqSample():times, temps, hums =getHistData (2) fmt ='%Y-%m-%d %H:%M:%S' tstamp0 =datetime.strptime(times[0], fmt) tstamp1 =datetime.strptime(times[1], fmt) freq =tstamp1-tstamp0 freq =int(round(freq.total_seconds()/60)) return (freq) 

Once we we have this frequency parameter in minutes, we will show it on index.html and asking for a “rangeTime” number of minutes to be send back to our server ==> @app.route(‘/’, methods=[‘POST’]):

@app.route('/', methods=['POST'])def my_form_post():global numSamples global freqSamples global rangeTime rangeTime =int (request.form['rangeTime']) if (rangeTime  numMaxSamples):numSamples =(numMaxSamples-1) 

The picture shows the result:

Eliminating Possible errors when constructing the graphs:

Ocasionally, strange (or corrupted) data can be storaged on database, jeopardizing our analysis. Those data can be verified (or cleaneed) on several places (like during the time sensor are capturing the data, etc). But once the script that display data is independent of the one that logged the data, let’s “cap” the maximum and minimum values of our sensors, before using the data to buit the graphs. This can be achieved with the function testData(temps, hums) :

# Test data for cleanning possible "out of range" valuesdef testeData(temps, hums):n =len(temps) for i in range(0, n-1):if (temps[i] <-10 or temps[i]>50):temps[i] =temps[i-2] if (hums[i] <0 or hums[i]>100):hums[i] =temps[i-2] return temps, hums 

The scripts for this new version can be download from my GitHub: dhtWebHist_v2

Step 18:Conclusion

As always, I hope this project can help others find their way into the exciting world of electronics!

For details and final code, please visit my GitHub depository: RPI-Flask-SQLite

For more projects, please visit my blog: MJRoBot.org

Saludos from the south of the world!

See you at my next tutorial!

Thank you,

Source:From Data to Graph:A Web Journey With Flask and SQLite


Processus de fabrication

  1. Micropuce :ADC 24 bits et 16 bits avec des débits de données jusqu'à 153,6 kSPS
  2. Moniteur de température et d'humidité domestique (pièce) avec graphique Web – Raspberry Pi
  3. Créer des robots avec Raspberry Pi et Python
  4. Accélérer la transformation numérique avec les données IoT, grâce à Cisco et IBM
  5. Exploiter les données IoT de la périphérie vers le cloud et vice-versa
  6. Le parcours IIoT commence par la télémétrie à distance
  7. Comment rendre l'IOT réel avec Tech Data et IBM Part 2
  8. Comment rendre l'IoT réel avec Tech Data et IBM Part 1
  9. Produire des résultats commerciaux avec des projets Big Data et l'IA