Outils pour utilisateurs

Outils du site


meteo_2eme_seance

Création d'un script python

Au cours de cette deuxième séance, nous allons construire pas à pas un script python.

Pourquoi construire un script ?

Lors de la première séance, nous avons découvert comment lire les données du capteur DHT22 en mode interactif dans le terminal Python. Ce mode est idéal pour expérimenter, tester et comprendre le fonctionnement de la sonde. Mais il a ses limites : chaque mesure doit être lancée manuellement, les calculs doivent être refaits à la main, et les résultats ne sont pas sauvegardés.

Avec un script Python autonome, on passe à l'étape supérieure : notre station météo devient automatisée et réutilisable. Le code tourne en boucle, effectue les relevés à intervalle régulier, calcule automatiquement le point de rosée et l’humidex, puis affiche les résultats joliment formatés. C’est une première vraie brique vers une station météo libre et autonome, que l’on peut faire évoluer ensuite (enregistrement des données, affichage web, alertes, etc.). On quitte l’expérimentation manuelle pour poser les bases d’un service automatisé, éthique, et maîtrisé de bout en bout. Bref : on libère notre météo.

Création du script

Créer un script et éditer le avec la commande suivante :

nano meteo_dht22.py

Importation

Commençons par importer la bibliothèque Adafruit_DHT, qui permet de lire les données des capteurs DHT (température et humidité).

import Adafruit_DHT

Imports supplémentaires :

  • time pour gérer les temporisations entre les mesures.
  • math pour les calculs scientifiques.
  • datetime pour afficher la date et l'heure des relevés.
import time
import math
from datetime import datetime

Différences entre import et from ... import ...

Quand on écrit import math, on importe toute la bibliothèque, et on accède à ses fonctions avec le préfixe math. (ex : math.log()).

Quand on écrit from datetime import datetime, on importe directement une fonction ou une classe précise, ce qui permet de l’utiliser sans préfixe (ex : datetime.now() au lieu de datetime.datetime.now()).

La première forme est plus explicite et lisible dans les grands scripts, la seconde est plus concise quand on utilise souvent la même fonction.

Déclaration du capteur

DHT_SENSOR = Adafruit_DHT.DHT22  
DHT_PIN = 4

Ici, on déclare deux constantes : DHT_SENSOR pour indiquer le type de capteur utilisé (le DHT22), et DHT_PIN pour spécifier sur quelle broche GPIO le capteur est branché.

On parle de constante car ces valeurs ne changent pas pendant l’exécution du script. On les écrit en majuscules pour le signaler clairement (c’est une convention en Python).

L’intérêt ? C’est plus lisible, plus facile à modifier si on change de capteur ou de broche, et ça évite de répéter ces valeurs partout dans le code. On améliore donc la clarté et la maintenabilité du programme.

Les fonctions

Dans le script, on trouve deux blocs qui commencent par def. Ce sont des fonctions, c’est-à-dire des morceaux de code réutilisables qui effectuent une tâche bien précise :

def calculer_point_de_rosee(temp, hum):

...

def calculer_humidex(temp, hum):

---

Une fonction, c’est comme une boîte à outils : on lui donne des données en entrée (ici, la température et l’humidité), et elle nous renvoie un résultat calculé (le point de rosée ou l’humidex). On peut ensuite réutiliser cette fonction autant de fois qu’on veut, sans devoir réécrire le calcul à chaque fois.

Les fonctions permettent de structurer le code, de le rendre plus clair, plus facile à maintenir et à faire évoluer. C’est un pas de plus vers un code propre, compréhensible
def calculer_point_de_rosee(temp, hum):
    # Formule pour calculer le point de rosée
    alpha = 17.27
    beta = 237.7
    gamma = (alpha * temp) / (beta + temp) + math.log(hum / 100.0)
    point_de_rosee = (beta * gamma) / (alpha - gamma)
    return point_de_rosee

Fonction pour calculer le point de rosée, une mesure liée à la condensation de l’humidité (formule d’August-Roche-Magnus).

Le mot-clé return sert à renvoyer un résultat depuis une fonction. C’est ce que la fonction renvoie à celui qui l’a appelée. Sans return, la fonction ferait les calculs, mais ne transmettrait rien de ses résultats !

def calculer_humidex(temp, hum):
    # Formule pour calculer l'humidex
    humidex = temp + (5/9) * (6.11 * math.exp(5417.7530 * ((1/273.16) - (1/273.15))) - 10)
    return humidex

Fonction pour calculer l’humidex, un indice qui combine température et humidité pour donner une idée de la température ressentie.

Boucle infinie

Dans notre script, on utilise une boucle infinie grâce à la ligne :

while True:

Cela signifie que le bloc de code qui suit va s’exécuter en boucle, sans fin, tant qu’on n’interrompt pas manuellement le programme. Cette technique est parfaite pour une station météo autonome : elle va relever les données, les afficher, attendre un peu… puis recommencer, encore et encore. C’est ce qui permet de transformer notre Raspberry Pi en véritable service météo libre et auto-hébergé, toujours actif tant que la machine est allumée.

Les variables

humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)

on utilise deux variables, humidity et temperature. Une variable, c’est comme une boîte dans laquelle on peut stocker une valeur pour la réutiliser plus tard, contrairement aux constantes, ici la valeur sera amenée à bouger. La fonction read_retry() interroge le capteur et renvoie deux valeurs : l’humidité et la température mesurées. On les dépose directement dans deux variables, pour pouvoir les afficher et/ou faire des calculs,

En nommant les variables de façon claire, on rend le code plus compréhensible et plus facile à relire.

Validité de la lecture

Une condition permets de vérifier si la lecture de la sonde est valable. Si la lecture est correcte, le programme continue normalement, sinon, un message d'erreur s'affiche.

    if humidity is not None and temperature is not None:
         # Suite du programme
    else:
         # Message en cas d'erreur

Date et heure

Dans notre station météo, on veut savoir quand chaque mesure a été prise. Pour ça, on utilise le module datetime, et plus précisément les lignes suivantes :

now = datetime.now()
date_heure = now.strftime("%d-%m-%Y %H:%M:%S")
  • datetime.now() récupère la date et l’heure actuelles du système.
  • strftime() permet de formater cette date dans un style plus lisible : ici, jour-mois-année heure:minute:seconde.

Calcul du point de rosée et de l'humidex

Après avoir lu la température et l'humidité, on utilise les fonctions qu’on a définies plus haut pour effectuer deux calculs :

point_de_rosee = calculer_point_de_rosee(temperature, humidity)
humidex = calculer_humidex(temperature, humidity)

Ces lignes montrent comment on réutilise nos fonctions calculer_point_de_rosee() et calculer_humidex() en leur passant les variables temperature et humidity en paramètres. Les résultats obtenus sont ensuite stockés dans deux nouvelles variables, point_de_rosee et humidex.

Cela montre la force des fonctions : une fois écrites, on peut les appeler facilement autant de fois qu’on veut, ce qui rend notre code modulaire, réutilisable et lisible.

Couleurs ANSI

Nous pouvons ajouter en haut de notre script de nouvelles constantes avec les couleurs :

RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
BLUE = "\033[94m"
MAGENTA = "\033[95m"
RESET = "\033[0m"

Grâce aux constantes, nous obtiendrons un code plus compréhensible.

Affichage des données

Nous utilisons les couleurs pour rendre l'affichage plus clair et agréable à lire dans le terminal.

print(f"{BLUE}Date et heure:{RESET} {date_heure}")
print(f"{GREEN}Température:{RESET} {temperature:.1f}°C")
print(f"{YELLOW}Humidité:{RESET} {humidity:.1f}%")
print(f"{RED}Point de rosée:{RESET} {point_de_rosee:.1f}°C")
print(f"{MAGENTA}Humidex:{RESET} {humidex:.1f}")
print("----")

Les variables numériques sont affichés avec une seule décimale grâce à la syntaxe {temperature:.1f}. Ce format permet d’avoir des valeurs précises mais lisibles, sans afficher une longue série de chiffres inutiles. Chaque ligne correspond à une donnée spécifique.

Erreur de lecture de la sonde

En cas d’échec de la lecture, un message d’erreur est affiché. C’est important pour diagnostiquer les soucis matériels ou de câblage.

else:
    print("Échec de la lecture du capteur")

Pause entre les lectures

Mettons une pause de 10 secondes entre deux lectures, pour éviter de surcharger le capteur et ralentir le flux d’informations.

time.sleep(10)

Bonus : Ajouter la pression atmosphérique avec l’API OpenWeather

Afficher la pression atmosphérique récupérée sur Internet, en complément des données relevées par la sonde DHT22 sur le Raspberry Pi.

Créer un compte sur OpenWeather

  1. Cliquer sur “Sign in” en haut de la page.
  2. Cliquer sur “Create an account”.
  3. Remplir le formulaire et valider le compte.
  4. Cliquer sur “My API keys”.

  1. copier la clé affichée (garde-la précieusement !).

Installer la bibliothèque requests

Nous allons utiliser la bibliothèque requests pour faire des appels à l’API. Dans votre environnement virtuel Python, vous pouvez taper cette commande :

pip3 install requests

Dans le haut de votre script, ajoutez l'import de cette bibliothèque :

import requests

Nouvelles constantes

Ajoutons 4 nouvelles constantes :

  • Dans la section des couleurs, vous pouvez ajouter une couleur pour l'affichage de la pression atmosphérique.
CYAN = "\033[96m"
  • Créer une nouvelle section pour les coordonnées GPS d'Arles.
# Coordonnées GPS d'Arles
LATITUDE = 43.6768
LONGITUDE = 4.6303
  • Enfin, ajouter la clé API.
# Clé API
API_KEY = "Votre_clé"
Attention : Ici, nous mettons directement la clé API dans le code. En faisant cela, nous créons une faille de sécurité car nous exposons publiquement une donnée sensible. Nous verrons à la fin comment sécuriser notre clé API.

Création d'une nouvelle fonction

Cette fonction interroge le service météo OpenWeather pour récupérer la pression atmosphérique actuelle en fonction de la position géographique (latitude/longitude).

def get_pression_openweather(API_KEY, LATITUDE, LONGITUDE):

Elle prend en paramètre :

  • API_KEY → la clé personnelle d’API fournie par OpenWeather,
  • LATITUDE → la latitude du lieu (ex : 43.676 pour Arles),
  • LONGITUDE → la longitude du lieu (ex : 4.630 pour Arles).

URL de l'API

url = f"https://api.openweathermap.org/data/2.5/weather?lat={LATTITUDE}&lon={LONGITUDE}&appid={API_KEY}&units=metric&lang=fr"

On construit dynamiquement l’adresse de l’API avec les bonnes informations :

  • lat et lon pour la géolocalisation,
  • appid pour inclure la clé d’accès API,
  • units=metric pour avoir les données en °C et hPa,
  • lang=fr pour avoir les descriptions météo en français (utile si on affiche d'autres infos comme la description du ciel).

Bloc try/except

Le mot-clé try signifie : essaie d’exécuter les instructions suivantes. Cela permet d’éviter les plantages du script si une erreur survient (ex : pas de connexion Internet, clé API invalide…).

try:
    ....
    code de la fonction
    ....
except:
    ....
    code en cas d'échec de la fonction
    ....

Réponse de l'API

Appel de l'API

On utilise la bibliothèque requests pour envoyer une requête HTTP vers l’URL de l’API OpenWeather.

response = requests.get(url)

Conversion de la réponse en JSON

La méthode .json() transforme la réponse en dictionnaire Python. Cela nous permet de manipuler facilement les informations retournées par l’API.

data = response.json()

Exemple d'une structure JSON :

{
  "main": {
    "temp": 18.5,
    "pressure": 1013,
    "humidity": 82
  }
}

Récupération de la pression atmosphérique

pression = data["main"]["pressure"]

Ici, on accède à la donnée “pressure” qui se trouve dans la clé “main” du dictionnaire. C’est cette valeur (en hPa) que l’on souhaite récupérer.

Retour de la fonction

return pression

On retourne la valeur de la pression. Cela signifie que lorsque cette fonction est appelée, elle renverra un nombre (par exemple 1013).

Gestion des erreurs

except:
    return None

Si quelque chose ne fonctionne pas (problème de réseau, mauvaise clé API, réponse inattendue, etc.), on retourne None.

Affichage des données

pression = recuperer_pression(API_KEY, LATITUDE, LONGITUDE)

On utilise ici la fonction recuperer_pression (définie plus haut) pour obtenir la pression atmosphérique actuelle à partir des coordonnées géographiques (latitude et longitude) et de la clé API. Le résultat (la pression en hPa) est stocké dans la variable pression.

if pression is not None:
-> if humidity is not None and temperature is not None and pression is not None:

On s’assure que la récupération des données a bien fonctionné. Si la valeur n’est pas None, cela veut dire que l’appel à l’API a réussi, donc on peut afficher la donnée. Sinon, on ne fait rien (ou on pourrait afficher un message d’erreur pour informer l’utilisateur).

print(f"{CYAN}Pression atmosphérique:{RESET} {pression} hPa")

On affiche la pression, en couleur cyan, grâce aux constantes ANSI définies auparavant (CYAN et RESET). La valeur est suivie de l’unité hPa (hectopascals), utilisée en météorologie pour mesurer la pression atmosphérique.

meteo_2eme_seance.txt · Dernière modification : 2025/04/25 11:41 de admin