Surveillez la température et l’humidité de votre maison avec Raspberry Pis et Prometheus


  • Français


  • Les données sont belles. En tant que #CitizenScientist, j’aime collecter des données et essayer de donner un sens au monde qui m’entoure. Au travail, nous utilisons Prométhée pour collecter des données métriques de nos clusters, et à la maison, j’utilise Prometheus pour collecter des données de mes loisirs. Cet article explique comment utiliser une application (un script Python qui collecte les données de température et d’humidité d’un capteur) et l’instrumenter pour fournir des données dans un modèle que Prométhée peut rassembler. je vais aussi créer un service systemd pour démarrer et gérer l’application.

    Qu’est-ce que Prométhée ?

    Prometheus est un système de surveillance et d’alerte open source qui rassemble des métriques et fournit un langage de requête puissant pour explorer les données. J’ai écrit sur la configuration de Prometheus localement à la maison. Prometheus est fréquemment utilisé pour collecter des données à partir de clusters d’orchestration de conteneurs tels que Kubernetes et OpenShift.

    Dans mon travail en tant qu’ingénieur de fiabilité de site exécutant des clusters dédiés OpenShift pour Red Hat, Prometheus est au cœur d’un système de surveillance et d’alerte robuste pour tous nos clusters, les opérateurs, et les candidatures. Il est utilisé à grande échelle par les grandes entreprises, mais il est également à la maison, enfin, à la maison, collectant des données pour des projets d’amateurs.

    Dans mon article précédent sur l’utilisation d’un Raspberry Pi Zero et DHT22 pour collecter des données de température et d’humidité, j’ai montré comment écrire un script Python pour collecter les données et les imprimer à l’écran. C’est bien pour vérifier les données manuellement à chaque instant, mais il serait beaucoup plus utile pour moi de rassembler et de stocker les données pour les examiner historiquement. C’est là que Prometheus brille en tant que base de données de séries chronologiques avec son propre langage de requête et ses capacités graphiques.

    Instrumenter l’application pour Prometheus

    En un mot, instrumenter l’application pour Prometheus nécessite de prendre les données du capteur, de les étiqueter et de les servir sous forme de texte sur HTTP afin que Prometheus puisse trouver et stocker les données. Prometheus vérifiera ces pages de texte, ou « cibles », à un intervalle spécifié, à la recherche de mises à jour des données. Ainsi, l’application devra mettre à jour les métriques cibles à mesure que de nouvelles données de capteur sont reçues.

    Le format des données exposées à Prometheus à collecter se compose d’une clé (un nom de métrique – celle qui est mesurée) et d’une valeur séparée par un espace :

    dht22_temperature{scale="fahrenheit"} 84.01999931335449

    Prometheus prend également en charge les étiquettes facultatives pour faciliter le filtrage et l’agrégation des données. Cette application utilise des étiquettes pour différencier les échelles Celsius et Fahrenheit pour le dht22_temperature métrique. le {scale="fahrenheit"} est l’étiquette dans l’exemple ci-dessus. Vérifiez Modèle de données Prométhée pour plus de détails.

    Vous pouvez modifier le script manuellement pour configurer un serveur Web et imprimer les données du capteur, mais Prometheus fournit un Client Python Prometheus cela rend le processus considérablement plus facile. Vous pouvez installer le client à l’aide du gestionnaire de packages pip Python. Si vous ne l’avez pas déjà, installez pip à l’aide du gestionnaire de paquets de votre distribution, puis utilisez-le pour installer prometheus-client. J’exécute le système d’exploitation Raspberry Pi sur mon système de capteurs, je vais donc utiliser apt-get, mais remplacez votre gestionnaire de paquets de votre choix :

    # Install pip
    sudo apt-get install pip3

    # Install prometheus-client
    sudo pip3 install prometheus-client

    Ensuite, vous devez modifier le script du capteur de l’article précédent pour stocker les données du capteur sous la forme Jauges Prométhée. Une jauge est “une métrique qui représente une valeur numérique unique qui peut monter et descendre arbitrairement”, par opposition à, disons, un compteur, qui ne fait que monter. Prometheus a de nombreux types de métriques différents. Une jauge est parfaite pour représenter les données de température et d’humidité.

    Les jauges sont fournies par le prometheus_client.Gauge module, vous devez donc importer le module avant de pouvoir utiliser des jauges dans le script. Parce que start_http_server est utilisé plus tard pour afficher les métriques via HTTP, importez-les maintenant également :

    # Import Gauge and start_http_server from prometheus_client
    from prometheus_client import Gauge, start_http_server

    Ensuite, créez les jauges pour stocker les données d’humidité et de température. le ['scale'] bit ajoute l’étiquette “échelle” pour la jauge de température. Ensuite, la jauge est initialisée avec les deux celsius et fahrenheit valeurs pour l’étiquette :

    # Create Prometheus gauges for humidity and temperature in
    # Celsius and Fahrenheit
    gh = Gauge('dht22_humidity_percent',
               'Humidity percentage measured by the DHT22 Sensor')
    gt = Gauge('dht22_temperature',
               'Temperature measured by the DHT22 Sensor', ['scale'])

    # Initialize the labels for the temperature scale
    gt.labels('celsius')
    gt.labels('fahrenheit')

    Vous pouvez définir les jauges avec les données du capteur lors de la vérification du capteur :

        try:
            # Get the sensor data
            humidity, temperature = Adafruit_DHT.read_retry(SENSOR, SENSOR_PIN)
        except RuntimeError as e:
            log.error("RuntimeError: {}".format(e))

        if humidity is not None and temperature is not None:
            # Update the gauge with the sensor data
            gh.set(humidity)
            gt.labels('celsius').set(temperature)
            gt.labels('fahrenheit').set(celsius_to_fahrenheit(temperature))

    Cela se fait à l’intérieur d’un while True: boucle (non illustrée ci-dessus ; voir le script complet ci-dessous) pour mettre continuellement à jour les jauges avec les données du capteur.

    Enfin, Prométhée start_metrics_server servira les métriques collectées via HTTP. C’est ce qu’on appelle avant le while boucle pour que le serveur démarre en premier :

        # Start the Prometheus metrics server to display the metrics data
        metrics_port = 8000
        start_http_server(metrics_port)

    Avec tout cela ensemble, le script devrait ressembler à ceci :

    #!/usr/bin/env python3

    import logging
    import time

    import Adafruit_DHT

    from prometheus_client import Gauge, start_http_server
    from systemd.journal import JournalHandler

    # Setup logging to the Systemd Journal
    log = logging.getLogger('dht22_sensor')
    log.addHandler(JournalHandler())
    log.setLevel(logging.INFO)

    # Initialize the DHT22 sensor
    # Read data from GPIO4 pin on the Raspberry Pi
    SENSOR = Adafruit_DHT.DHT22
    SENSOR_PIN = 4

    # The time in seconds between sensor reads
    READ_INTERVAL = 30.0

    # Create Prometheus gauges for humidity and temperature in
    # Celsius and Fahrenheit
    gh = Gauge('dht22_humidity_percent',
               'Humidity percentage measured by the DHT22 Sensor')
    gt = Gauge('dht22_temperature',
               'Temperature measured by the DHT22 Sensor', ['scale'])

    # Initialize the labels for the temperature scale
    gt.labels('celsius')
    gt.labels('fahrenheit')

    def celsius_to_fahrenheit(degrees_celsius):
            return (degrees_celsius * 9/5) + 32

    def read_sensor():
        try:
            humidity, temperature = Adafruit_DHT.read_retry(SENSOR, SENSOR_PIN)
        except RuntimeError as e:
            # GPIO access may require sudo permissions
            # Other RuntimeError exceptions may occur, but
            # are common.  Just try again.
            log.error("RuntimeError: {}".format(e))

        if humidity is not None and temperature is not None:
            gh.set(humidity)
            gt.labels('celsius').set(temperature)
            gt.labels('fahrenheit').set(celsius_to_fahrenheit(temperature))

            log.info("Temp:{0:0.1f}*C, Humidity: {1:0.1f}%".format(temperature, humidity))

        time.sleep(READ_INTERVAL)

    if __name__ == "__main__":
        # Expose metrics
        metrics_port = 8000
        start_http_server(metrics_port)
        print("Serving sensor metrics on :{}".format(metrics_port))
        log.info("Serving sensor metrics on :{}".format(metrics_port))

        while True:
            read_sensor()

    Configurer l’unité systemd et la journalisation

    Le script est prêt à fonctionner et fonctionnerait avec Prometheus tel quel. Mais je l’exécute sur sans tête (c’est-à-dire sans moniteur, clavier, etc.) Raspberry Pi Zero Ws installé dans des boîtiers de projet avec des capteurs DHT22, installés dans différentes pièces de la maison. Je vais ajouter un service systemd pour démarrer automatiquement le script au démarrage et m’assurer qu’il continue de fonctionner. Je vais également profiter du journal systemd et envoyer les données de journal du script (par exemple, les messages de démarrage ou d’erreur) au journal.

    Le service systemd sera un fichier séparé utilisé par systemd, mais il a besoin du python3-systemd package pour envoyer les journaux au journal à partir du script. Vous pouvez l’installer avec apt-get (ou votre gestionnaire de paquets) :

    # Install the python3-systemd package for Journal integration
    sudo apt-get install python3-systemd

    Vous pouvez configurer le consignateur Python dans le script du moniteur de service pour envoyer des journaux au journal en utilisant le systemd.journal.JournalHandler module. Après l’avoir importé, vous pouvez ajouter le JournalHandler en tant que gestionnaire pour le logger :

    from systemd.journal import JournalHandler

    # Setup logging to the Systemd Journal
    log = logging.getLogger('dht22_sensor')
    log.addHandler(JournalHandler())
    log.setLevel(logging.INFO)

    Maintenant, il peut se connecter au journal avec log.info(). Par example:

    # This will send the message to the Systemd Journal,
    # and show up in `systemctl status` and with `journalctl`
    log.info("Serving sensor metrics on :{}".format(metrics_port))

    Avec le script mis à jour pour vous connecter au journal systemd, créez un service systemd pour le sensor-metrics.py scénario:

    # /etc/systemd/system/sensor-metrics.service
    [Unit]
    Description=DHT22 Sensor Metrics Service
    After=network.target
    StartLimitIntervalSec=0[Service]
    Type=simple
    Restart=always
    ExecStart=python3 /opt/sensor-metrics/sensor-metrics.py

    [Install]
    WantedBy=multi-user.target

    Cela indique simplement à systemd de rechercher un script dans /opt/sensor-metrics/sensor-metrics.py, démarrez-le et laissez-le fonctionner. Cela deviendra le sensor-metrics un service.

    Liez (ou déplacez, si vous préférez) le sensor-metrics.py script à /opt/sensor-metrics/sensor-metrics.py:

    # Create /opt/sensor-metrics and link the sensor-metrics.py script from the current directory into it
    sudo mkdir /opt/sensor-metrics
    sudo ln -s $(pwd)/sensor-metrics.py /opt/sensor-metrics/

    Lier le sensor-metrics.service fichier à /etc/systemd/system:

    # Link the sensor-metrics.service file into the Systemd directory
    sudo ln -s $(pwd)/sensor-metrics.service /etc/systemd/system/

    Vous pouvez maintenant activer le service sensor-metrics pour démarrer au démarrage et vérifier l’état :

    # Enable and start the sensor-metrics.service
    sudo systemctl enable sensor-metrics.service
    sudo systemctl start sensor-metrics.service

    Le service est maintenant en cours d’exécution et configuré pour démarrer au démarrage.

    Pour savoir si tout fonctionne, vérifiez l’état du service avec systemctl:

    sudo systemctl status sensor-metrics.service

    Vous devriez voir quelque chose comme ceci (si tout fonctionne):

    ● sensor-metrics.service - DHT22 Sensor Metrics Service
       Loaded: loaded (/home/chris/sensor-metrics.service; enabled; vendor preset: enabled)
       Active: active (running) since Wed 2021-06-30 03:33:02 BST; 8s ago
     Main PID: 4129 (python3)
        Tasks: 2 (limit: 877)
       CGroup: /system.slice/sensor-metrics.service
               └─4129 /usr/bin/python3 /opt/sensor-metrics/sensor-metrics.py

    Jun 30 03:33:02 cumulo systemd[1]: Started DHT22 Sensor Metrics Service.
    Jun 30 03:33:05 cumulo /opt/sensor-metrics/sensor-metrics.py[4129]: Serving sensor metrics on :8000
    Jun 30 03:33:05 cumulo /opt/sensor-metrics/sensor-metrics.py[4129]: Temp:30.6*C, Humidity: 47.1%

    Succès!

    Vérifier la cible des métriques

    Avec le service en cours d’exécution et le script modifié pour collecter les données des capteurs dans les jauges et les afficher pour Prometheus, vous pouvez afficher les données comme Prometheus le fera.

    Dans un navigateur, accédez à http://<IP OF YOUR HOST>:8000, en remplaçant l’adresse IP de la machine exécutant le service sensor-metrics.

    Vous devriez voir une page avec plusieurs métriques sur le client Python (bonus !), ainsi que les métriques dht22_temperature et dht22_humidity. Ça devrait ressembler a quelque chose comme ca:

    Les données sont vraiment belles ! Regarde ça! Humidité et température à deux échelles différentes !

    Les données seront mises à jour chaque fois que le script de service vérifiera les données du capteur. Passons maintenant à la dernière étape : montrer à Prometheus où rechercher toutes ces données.

    Créer une configuration de scrape Prometheus

    Avant de continuer, je vous recommande de lire mon article précédent sur l’exécution de Prometheus à la maison et d’avoir une instance déjà configurée. Si vous ne l’avez pas encore fait, allez-y et faites-le maintenant (et dites à tous vos amis que c’était une expérience formidable). L’article montre comment configurer Prometheus pour lire les configurations de scrape dynamique à partir d’un fichier et les recharger automatiquement. Ces configurations de grattage pointent Prometheus vers les cibles de données métriques qu’il devrait ingérer (c’est-à-dire « gratter »).

    Ajoutez une configuration de scrape pour les données de métriques de capteur au tableau (le cas échéant) dans la configuration JSON de la configuration de scrape dans l’article précédent. Notez que le tableau ci-dessous a la seule cible de métriques de capteur Prometheus. Le vôtre a peut-être déjà d’autres cibles. Ajoutez simplement à la liste.

    // This scrape config target points to the IP Address of the Raspberry Pi and the Port used in the sensor-metrics.py script
    // Substitute your own IP and the port you chose
    [
      {"labels": {"job": "dht22"}, "targets": ["192.168.1.119:8000"]}
    ]

    Après avoir redémarré Prometheus (ou en attendant qu’il trouve et charge la nouvelle configuration de scrape), Prometheus commencera à rechercher des données de métriques sur la cible que vous avez spécifiée ci-dessus.

    Rassembler le tout

    Enfin, tout fonctionne et vous pouvez regarder les données que vous collectez ! Ouvrez l’interface Web Prometheus pour votre serveur Prometheus. Le mien est http://localhost:9090/graph, et le vôtre peut être le même si vous avez suivi l’article précédent. Cliquez sur l’onglet “graphique” et recherchez dht22_temperature{scale=~"fahrenheit"} pour voir les données de température collectées.

    Bien. C’est décevant.

    Bon alors, deux choses :

    1. Les données de séries chronologiques sont décevantes au début car vous n’avez pas encore beaucoup de données. Cela s’améliore avec le temps.
    2. Les données de température ambiante prennent un peu plus de temps pour afficher quelque chose d’intéressant car elles ne changent pas beaucoup.

    Alors, laissez-lui le temps. Finalement, cela semblera beaucoup plus intéressant et s’améliorera :

    BEAUCOUP mieux !

    Faites de la #CitizenScience

    Prometheus fonctionne très bien pour collecter des données métriques, les stocker sous forme de données de séries chronologiques et fournir un moyen de les explorer. J’espère que cet article vous a inspiré pour faire de la #CitizenScience à la maison, créer vos propres données et explorer !

    Source

    Houssen Moshinaly

    Pour contacter personnellement le taulier :

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

    Copy code