Flask temps réel avec RASPBERRY

 Nous avons vu dans le tutoriel sur la sonde DS18B20 comment mesurer la température à l'aide d'un Raspberry. Le projet que je vous présente aujourd'hui explique comment on peut, à partir de ces données, créer une courbe de température consultable à l'aide d'un navigateur, simplement en utilisant Python et la librairie flask.

Réaliser des courbes de température avec DS18B20

Voici un aperçu de ce que l'on va faire :

Capture d'écran objectif projet Capture d'écran objectif projet

Prérequis

Pour ce projet, il faut le même matériel que dans le tutoriel sur la mesure de température, rien de plus. Ce qui donne dans le détail :

Une fois tout le matériel réunis, on peut passer au branchement.

Branchement de la sonde

Ici encore, rien de nouveau, on garde le même branchement que dans le tuto, soit :

Shéma de branchement d'une DS18B20 sur Raspberry Pi 3

Maintenant que la sonde est branchée, on essaie de mesurer la température via le terminal pour tester la liaison. (Voir le III. du tuto sur la sonde)

Installation de Flask et premiers pas

Important ! Tout au long du projet, il faudra exécuter le fichier app.py avec la commande suivante :

sudo python3 app.py
Si l'on n'indique pas la version de Python 3, le script ne s'exécutera pas.

Pour commencer, il va falloir installer la librairie flask qui va nous permettre de faire de notre Raspberry Pi un serveur Web. Entrez simplement la commande suivante dans le terminal :

sudo apt-get install python3-flask

Maintenant que la librairie est installée, voyons les notions de base de Flask. Voici le code le plus simple utilisant la librairie que l'on peut écrire :

from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello world !'
app.run(debug=True, host='0.0.0.0', port=5000)

En exécutant ce code, on devrait voir s'écrire dans le terminal ceci :

* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger pin code: xxx-xxx-xxx

Cela signifie que le serveur est démarré, et qu’on peut y accéder en entrant l'IP du Raspberry Pi, suivi de :5000, qui est le numéro du port. Si on accède à cette page, on verra s'afficher Hello World.
Pour tester, entrer ceci dans le champ URL d'un navigateur : xxx.xxx.x.xxx:5000, où xxx.xxx.x.xxx est l'adresse IP du Raspberry Pi.
Si vous ne connaissez pas l'adresse IP de votre Raspberry Pi, entrez dans une console ceci :

hostname -I

(et n'oubliez pas de redémarrer le serveur)


Capture d'écran premier script Flask

Plutôt que de renvoyer un simple texte, Flask peut retourner une page HTML. Pour se faire, il suffit de changer le return 'Hello world' de la fonction appelée en celui-ci : return render_template('index.html').
La page index.html sera donc affichée sur le navigateur lorsque la fonction est appelée.
Pour transférer des variables entre le script Python et la page HTML, on ajoute simplement l'élément à transférer comme ceci : return render_template('index.html', valeur="2").
Pour récupérer la donnée transférée, il suffira d'écrire {{ valeur }} entre des balises HTML.

Prenons un exemple :
Créez les fichiers et répertoires comme ceci sur votre Raspberry Pi :

├──ProjetGraphTemp
    └── app.py
├── templates └── index.html
├── static (optionnel) └── style.css
Aide

Pour tout créer d'un coup, entrez ces commandes dans le terminal :

cd ~
mkdir ProjetGraphTemp
cd ProjetGraphTemp
touch app.py
mkdir templates
touch templates/index.html
mkdir static
touch static/style.css

Insérez le code suivant dans le fichier app.py :

from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html', nomSite = 'Raspberry Lab')
app.run(debug=True, host='0.0.0.0', port=5000)

Et celui-ci dans le fichier index.html :

<!DOCTYPE HTML>
<html>
<head>
<title>{{ nomSite }}</title>
</head>
<body>
<h1>Bienvenue sur {{ nomSite }} !</h1>
</body>
</html>

Enfin, changez le style d'écriture ou tout autre élément graphique dans le fichier css si vous le souhaitez. Pour faire le lien entre les documents HTML & CSS avec Flask, ajouter cette ligne dans la balise <head> du code HTML :

<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}" />

En exécutant le code Python et en se rendant à l'adresse IPRaspberry:5000, on obtient ceci :

Capture d'écran script avec redirection HTML Flask

On a donc les bases pour commencer par afficher la température sur une page Web.

Afficher la température

Avec ce que l'on vient de voir et ce que l'on a déjà vu dans tutoriel sur la sonde DS18B20, il n'est pas compliqué d'afficher la température sur une page HTML, il suffit de modifier un tout petit peu le code précédent.

#!/usr/bin/env python3
from flask import Flask, render_template
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
app = Flask(__name__)
# Fonction : Retourner la temperature actuelle et ordonner ou non son enregistrement
def getTemp(sauvegardeStatus):
# On ouvre le fichier de la sonde. Remplacer les X par le numero de la sonde
fichSonde = open("/sys/bus/w1/devices/28-XXXXXXXXXXXX/w1_slave")
contenu = fichSonde.read()
fichSonde.close()
# On 'nettoie' le contenu pour recuperer que la temperature
secondeLigne = contenu.split("\n")[1]
temperatureData = secondeLigne.split(" ")[9]
temperature = float(temperatureData[2:-2])
temperature = temperature / 10
return temperature
@app.route("/getTemp")
def affTemp():
return render_template('index.html', temp=getTemp(0))
app.run(debug=True, host='0.0.0.0', port=5000)
Information

Comment récupérer le numéro de la sonde ?

Il suffit d'entrer les commandes suivantes dans le terminal :

sudo modprobe w1-gpio
sudo modprobe w1-therm
ls /sys/bus/w1/devices/

Une ligne de ce type devrait s'afficher :

28-0317229e0bff  w1_bus_master1

La partie verte correspond au numéro de la sonde.
Si rien ne s'affiche, lire cette section du tutoriel sur la DS18B20.

<!DOCTYPE HTML>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<link rel = "icon" type = "image/png" href = "https://raspberry-lab.fr/ImgStat/Icon.png" />
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}" />
<title>Temperature</title>
</head>
<body>
<h1> Temperature actuelle : {{ temp }} </h1>
</body>
</html>

En exécutant le code Python et en se rendant à l'adresse IPRaspberry:5000/getTemp, on obtient ceci :

Capture d'écran script avec affichage température HTML Flask

Pour améliorer un peu l'esthétique, je vous propose ce CSS, qu'il faut ajouter dans le fichier static/style.css :

body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background-color: #F5F5F5;
}
h1 {
font-size: 4.5rem;
font-weight: 300;
margin: 0 0 0 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

En executant le code avec ce CSS, on obtient ceci :

Capture d'écran script avec redirection HTML Flask et CSS
Enregistrer les températures

Pour construire un graphique de température, on va avoir besoin de données, il va falloir enregistrer les températures à intervalle de temps régulier. On va pour se faire créer une fonction supplémentaire à notre code, que l'on va nommer enregistrement(temperature). Cette fonction va être appelée lorsque l'on fait un getTemp. Elle va enregistrer la température donnée en paramètre dans un fichier texte ayant pour nom la date du jour. Le fichier contiendra sur chaque ligne l'heure et la température associée.
Les fichiers contenant les données de température seront de cette forme :

00:00 18.625
00:15 18.437
00:30 18.312
00:45 18.125
01:00 18.0
01:15 17.812
01:30 17.5
01:45 17.375
02:00 17.312
Information J'ai déjà pensé à utiliser une base de donnée pour enregistrer les températures, mais le temps de chargement du graphique était beaucoup plus long que lorsque l'on vient lire le contenu des fichiers.

Voici la fonction enregistrement(temp), que j'explique juste après.

#Ajouter les imports suivants en debut de fichier
from datetime import datetime, timedelta
import os
# Entree : temperature; Fonction : enregistrer la temperature dans un fichier, au bon endroit
def enregistrement(temperature):
d = datetime.now()
# On recupere de datetime.now l'annee & le jour et on le stocke
annee = str(d)[:4]
jour = str(d)[:10]
repertoire = '/home/pi/ProjetGraphTemp/temperatures/' + annee + '/'
# On vérifie que le repertoire existe. S'il n'existe pas : on le cree
if not os.path.isdir(repertoire):
os.makedirs(repertoire)
fich_Temp = repertoire + jour + '.txt'
# On ouvre le fichier ayant pour nom la date_du_jour.txt en fonction de s'il existe ou pas : en add ou en write
if os.path.exists(fich_Temp):
# Le fichier existe, on l'ouvre en mode ajout
f = open(fich_Temp, "a")
else:
# Le fichier n'existe pas, on le cree et on l'ouvre
f = open(fich_Temp, "w")
# Enfin, on ajoute une ligne dans le fichier au format : HH:MM Temp _ Exemple : 10:15 27.02
time = d.strftime("%H:%M")
print(str(time) + " " + str(temperature), file=f)
f.close()

Cette fonction prend la température en paramètre. Tout d'abord, elle ouvre le fichier dans lequel la température va être enregistrée. Si le fichier n'existe pas déjà, on ouvre en mode w (write) : On crée le fichier et on écrit la première température dedans. Sinon, si le fichier existe déjà, (donc des températures ont déjà été enregistrées ce jour), en ouvre le fichier en mode a (add). Une fois le fichier ouvert ou créé, on écrit l'heure suivie de la température sur une nouvelle ligne

Pourquoi ouvrir en add plutot qu'en write ?
Si on ouvre le fichier en write, tout le contenu qui existait déjà serait écrasé. Il faut donc d'abord vérifier l'existence du fichier pour savoir si l'on utilise le mode add ou write.
De plus, on ne peut pas être en mode add si le fichier n'existe pas déjà.

Personnellement, j'enregistre la température toutes les 15 minutes. Modifions un peu la fonction getTemp en lui ajoutant un argument ordonnant ou non l'enregistrement de la température.

Pourquoi ne pas enregistrer la température à chaque getTemp ?
Car plus tard, on va calculer la moyenne de température de la journée et on va la comparer. Il faut donc avoir le même nombre de températures chaque jour, donc il faut qu'elle soit enregistrée seulement toutes les 15 minutes : Lorsque l'on va consulter la courbe, la température sera affichée mais pas enregistrée.

Voici donc le nouveau code après modifications :

#!/usr/bin/env python3
from flask import Flask, render_template
import RPi.GPIO as GPIO
from datetime import datetime, timedelta
import os
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
app = Flask(__name__)
# Entree : statut de sauvegarde; Fonction : Retourner la temperature actuelle et ordonner ou non son enregistrement
def getTemp(sauvegardeStatus):
# On ouvre le fichier de la sonde. Remplacer les X par le numero de la sonde
fichSonde = open("/sys/bus/w1/devices/28-XXXXXXXXXXXX/w1_slave")
contenu = fichSonde.read()
fichSonde.close()
# On 'nettoie' le contenu pour recuperer que la temperature
secondeLigne = contenu.split("\n")[1]
temperatureData = secondeLigne.split(" ")[9]
temperature = float(temperatureData[2:])
temperature = temperature / 1000
# sauvegardeStatus = 1 => on enregistre la temperature
if sauvegardeStatus == True :
enregistrement(temperature)
return temperature
def enregistrement(temperature):
d = datetime.now()
# On recupere de datetime.now l'annee & le jour et on le stocke
annee = str(d)[:4]
jour = str(d)[:10]
repertoire = '/home/pi/ProjetGraphTemp/temperatures/' + annee + '/'
# On verifie que le repertoire existe. S'il n'existe pas : on le cree
if not os.path.isdir(repertoire):
os.makedirs(repertoire)
fich_Temp = repertoire + jour + '.txt'
# On ouvre le fichier ayant pour nom la date_du_jour.txt en fonction de s'il existe ou pas : en add ou en write
if os.path.exists(fich_Temp):
# Le fichier existe, on l'ouvre en mode ajout
f = open(fich_Temp, "a")
else:
# Le fichier n'existe pas, on le cree et on l'ouvre
f = open(fich_Temp, "w")
# Enfin, on ajoute une ligne dans le fichier au format : HH:MM Temp _ Exemple : 10:15 27.02
time = d.strftime("%H:%M")
print(str(time) + " " + str(temperature), file=f)
f.close()
@app.route("/getTemp")
def affTemp():
return render_template('index.html', temp=getTemp(True))
app.run(debug=True, host='0.0.0.0', port=5000)

Il faut maintenant demander au Raspberry Pi de charger la page IPRasp:5000/getTemp?sauvegarde=True à intervalle régulier, je choisis 15 minutes mais vous pouvez choisir une autre fréquence évidemment. Pour se faire, on va modifier le fichier crontab.
Entrez donc la commande suivante dans le terminal :

sudo crontab -e
Information

Le fichier devrait ressembler à ceci :

# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.L71rF1/crontab installed on Tue May 29 20:57:03 2018)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command

Une fois le fichier ouvert en édition, ajoutez les lignes suivantes à la fin puis enregistrez et quittez. (la première ligne permet d'executer le programme dès le démarage du Raspberry Pi)

@reboot cd /home/pi/ProjetGraphTemp; sudo python3 app.py
*/15 * * * * curl localhost:5000/getTemp?sauvegarde=True

Grace à ces lignes, le Raspberry Pi exécutera le script app.py à chaque démarrage et enregistrera la température toutes les 15 minutes.

Google Charts permet de réaliser assez facilement un tas de graphique de tous types : Circulaires, histogrammes, cartes, courbes... Pour notre projet, nous allons utiliser le module de courbes : Line Chart

Pour commencer, on va créer une fonction fichierVersListe(cheminFich) qui va transformer les lignes contenues dans le fichier de température en deux listes qui vont nous servir plus tard pour la courbe et les statistiques.

def fichierVersListe(cheminFich):
f = open(cheminFich, "r")
points=[]
temperatures=[]
for line in f:
points.append([line[0:2], line[3:5], line[6:len(line) - 1]])
temperatures.append(float(line[6:len(line) - 1]))
f.close()
return [points, temperatures]
def moyenneListe(liste):
res=0
for i in liste:
res+=i
return (res/len(liste))
Fonction fichierVersListe(cheminFich)

Exemple d'éxecution de la fonction :

00:00 18.625
00:15 18.437
00:30 18.312
00:45 18.125
01:00 18.0

fichierVersListe(cetExemple)

[
                [['00', '00', '18.625'], ['00', '15', '18.437'], ['00', '30', '18.312'], ['00', '45', '18.125'], ['01', '00', '18.']],
[18.625, 18.437, 18.312, 18.125, 18.0]
            ]

fichierVersListe(cetExemple)[0]
Cette liste est la liste des points que l'on va dessiner sur le graphe.

[['00', '00', '18.625'], ['00', '15', '18.437'], ['00', '30', '18.312'], ['00', '45', '18.125'], ['01', '00', '18.']]

fichierVersListe(cetExemple)[1]
Cette liste permet de trouver très facilement la température max, min et moyenne.

[18.625, 18.437, 18.312, 18.125, 18.0]

On va maintenant se servir de tout ça en créant la fonction graphTemp(date) qui renverra sur la page HTML qui s'occupera de dessiner le graphe. La fonction est la fin du code final, tout est commenté et expliqué :

#!/usr/bin/env python3
from flask import Flask, render_template
import RPi.GPIO as GPIO
from datetime import datetime, timedelta
import os
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
app = Flask(__name__)
# Entree : statut de sauvegarde; Fonction : Retourner la temperature actuelle et ordonner ou non son enregistrement
def getTemp(sauvegardeStatus):
# On ouvre le fichier de la sonde. Remplacer les X par le numero de la sonde
fichSonde = open("/sys/bus/w1/devices/28-0317229e0bff/w1_slave")
contenu = fichSonde.read()
fichSonde.close()
# On 'nettoie' le contenu pour recuperer que la temperature
secondeLigne = contenu.split("\n")[1]
temperatureData = secondeLigne.split(" ")[9]
temperature = float(temperatureData[2:])
temperature = temperature / 1000
# sauvegardeStatus = 1 => on enregistre la temperature
if sauvegardeStatus == True :
enregistrement(temperature)
return temperature
# Entree : temperature; Fonction : enregistrer la temperature dans un fichier, au bon endroit
def enregistrement(temperature):
d = datetime.now()
# On recupere de datetime.now l'annee & le jour et on le stocke
annee = str(d)[:4]
jour = str(d)[:10]
repertoire = '/home/pi/ProjetGraphTemp/temperatures/' + annee + '/'
# On verifie que le repertoire existe. S'il n'existe pas : on le cree
if not os.path.isdir(repertoire):
os.makedirs(repertoire)
fich_Temp = repertoire + jour + '.txt'
# On ouvre le fichier ayant pour nom la date_du_jour.txt en fonction de s'il existe ou pas : en add ou en write
if os.path.exists(fich_Temp):
# Le fichier existe, on l'ouvre en mode ajout
f = open(fich_Temp, "a")
else:
# Le fichier n'existe pas, on le cree et on l'ouvre
f = open(fich_Temp, "w")
# Enfin, on ajoute une ligne dans le fichier au format : HH:MM Temp _ Exemple : 10:15 27.02
time = d.strftime("%H:%M")
print(str(time) + " " + str(temperature), file=f)
f.close()
# Entree : Chemin Absolu; Fonction : Retourner une liste contenant deux listes : une contenant les coordonnees de chaque
# point et une contenant uniquement les temperatures pour but de faire des statistiques
def fichierVersListe(cheminFich):
f = open(cheminFich, "r")
points = []
temperatures = []
for line in f:
# Voir explications sur le site
points.append([line[0:2], line[3:5], line[6:len(line) - 1]])
temperatures.append(float(line[6:len(line) - 1]))
f.close()
return [points, temperatures]
# Entree : Liste; Sortie : Moyenne de cette liste
def moyenneListe(liste):
res = 0
for i in liste:
res += i
return (res/len(liste))
@app.route("/getTemp")
def affTemp():
return render_template('index.html', temp=getTemp(True))
@app.route("/graphTemp")
def graphTempToday():
return graphTemp(None)
@app.route("/graphTemp/<date>")
def graphTemp(date):
if date is None:
# On a entre 192.xx.xx.xx/graphTemp sans indiquer de date, on affiche donc le graph du jour
d = datetime.now()
titre = "Temperature actuelle : " + str(getTemp(False))
else:
# Sinon, on affiche le graph de la date donnee | Ex : 192.xx.xx.xx/graphTemp/20180618
d = datetime.strptime(date, '%Y%m%d')
# Les 6 prochaines lignes permettent d'avoir un titre type : 08/09/2018 au lieu de 8/9/2018
strMonth = str(d.month)
strDay = str(d.day)
if len(strMonth) == 1:
strMonth = "0" + strMonth
if len(strDay) == 1:
strDay = "0" + strDay
dateTitle = strDay + "/" + strMonth + "/" + str(d.year)
titre = "Statistiques du " + dateTitle
# Liste contenant deux liste :
# pointsAndTemp[0] : coordonnees des points du graph;
# pointsAndTemp[1] : temperatures, permet de faire des stats : max,min,moy
pointsAndTemp = fichierVersListe("/home/pi/ProjetGraphTemp/temperatures/" + str(d)[:4] + "/" + str(d)[:10] + ".txt")
temperatures = pointsAndTemp[1]
# On calcule des dates precedantes et suivantes pour la navigation entre les jours
nextDate = d + timedelta(days=1)
prevDate = d - timedelta(days=1)
# On retourne tout a la page graphTemp.html
return render_template(
'graphTemp.html',
d = d.strftime("%Y-%m-%d"),
titre = titre,
temp = getTemp(False),
points = pointsAndTemp[0],
tempMin = round(min(temperatures), 1),
tempMax = round(max(temperatures), 1),
tempMoy = round(moyenneListe(temperatures), 1),
prevDate = prevDate.strftime("%Y%m%d"),
nextDate = nextDate.strftime("%Y%m%d")
)
app.run(debug=True, host='0.0.0.0', port=5000)

Enfin, voici le code HTML qui permet de transformer toutes les données transférées en un beau graphique, grâce à Google charts. Ce code est à enregistrer dans le fichier templates/graphTemp.html.

<!DOCTYPE HTML>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<link rel = "icon" type = "image/png" href = "http://espace-raspberry-francais.fr/ImgStat/Icon.png" />
<title>Graph du :{{ d }}</title>
<style media="screen" type="text/css">
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
background-color: #F5F5F5;
}
hr {
border-top: 1px solid #808080 !important;
margin: 0 2% 0 2%;
border: 0;
}
.fleches {
width: 4em;
margin: 0 7% 0 7%;
}
h1 {
font-size: 4.5rem!important;
font-weight: 300!important;
margin: 0 0 0 0 !important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
}
.bouton:not(:disabled):not(.disabled) {
cursor: pointer;
}
.bouton:hover {
background-color: #4582EC;
color: white;
}
.bouton {
border-radius: 1.078em;
font-size: 0.875em;
color: #4582EC;
background-color: transparent;
background-image: none;
border-color: #4582EC;
border: 1px solid ;
padding: 0.5rem 1.1rem;
font-family: inherit;
line-height: inherit;
margin-left: 17%;
width:10%;
}
a{
text-decoration: none !important;
}
.cadre {
margin-left: 1em;
margin-right: 1em;
}
.graph {
margin-left: -10%;
}
</style>
</head>
<body>
<h1>{{ titre }}</h1><br>
<ul style="font-size: 1.2em; margin-left: 5%">
<li>Temp. Moyenne : {{ tempMoy }} ({{ tempMin }} / {{ tempMax }})</li>
</ul><br>
<div class="" id="curve_chart"></div>
<hr>
<table width=100%>
<tr>
<th align=left><a href='/graphTemp/{{ prevDate }}'><img class="fleches" src='/static/prevDay.png'></a></th>
<th align=right><a href='/graphTemp/{{ nextDate }}'><img class="fleches" src='/static/nextDay.png'></a></th>
</tr>
</table>
</body>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('timeofday', 'Heure');
data.addColumn('number', 'Temperature');
data.addRows([
{%for point in points %}
[[parseInt({{point[0]}}),parseInt({{point[1]}}),0], {{point[2]}}],
{%endfor %}
]);
var options = {
curveType: 'function',
height: 600,
backgroundColor : "#F5F5F5",
animation:{duration: 1000, easing: 'out'},
lineWidth: 5,
series: { 0 : {color : "#1565c0"}},
legend: {position: 'none'},
chartArea: {
top: 20,
bottom: 60,
left:60,
right:60}
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
}
</script>
</html>
view rawgraphTemp.html hosted with ❤ by GitHub

Enregistrez les images de flèche permettant la navigation entre les dates en entrant les deux lignes de commande suivantes dans le terminal :

wget -P ~/ProjetGraphTemp/static https://raspberry-lab.fr/Projets/Courbe-temperature-accessible-avec-un-server-Web-Python/Images/nextDay.png
wget -P ~/ProjetGraphTemp/static https://raspberry-lab.fr/Projets/Courbe-temperature-accessible-avec-un-server-Web-Python/Images/prevDay.png

En laissant tourner le programme, la journée, on obtient des courbes comme ceci (avec un Raspberry à l'extérieur) :

Capture d'écran objectif projet Capture d'écran objectif projet

PS : J'ai ajouté une statistique "année précédente" dans mon programme car j'enregistre les températures avec mon Raspberry Pi depuis plusieurs années déjà ! :)


Voilà, ce projet est maintenant terminé, n'hésitez pas à laisser un commentaire pour dire si tout a bien marché, ou si vous avez quelques soucis. C'est le premier projet que j'explique entièrement, j'ai hâte de lire vos retours ! Ce projet peut évidemment être amélioré, avec des statistiques plus poussées, etc. La seule limite sera votre imagination !

Commentaires

Posts les plus consultés de ce blog

Comment fonctionne l'optimise d'Adam

RESEAU DE NEURONE CONVOLUTIF

Comment utiliser les diagrammes PlantUML dans Visual Studio Code pour Windows 10