Base RRD

トップ ページ

このメッセージに返信
著者: Frédéric
日付:  
To: Guilde
題目: Base RRD
Hello,

Il y a de cela une paire d'années, j'avais utilisé les rrdtools pour
monitorer une station météo Lacrosse ws2300.

Il y a belle lurette que cette station ne marche plus, et je suis en train
d'en refaire une from scratch¹. Et je voudrais ré-utiliser ce que j'avais
fait à l'époque.

Le hic, c'est qu'il me manque la partie création de la base RRD :o/ Est-ce
que quelqu'un saurait me dire comment il faut que je la définisse, à
partir du script de remplissage et de création des graphes joints ?

Merci d'avance !

¹ https://www.logre.eu/wiki/Anemometer

-- 
    Frédéric

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import os.path
import stat
import tempfile
import shutil

import rrdtool

RRD_FILENAME = "/var/lib/rrdtool/weather.rrd"
GRAPH_PATH = "/var/www/ws2300/images"
WIDTH = "400"
HEIGHT = "175"


def rrdUpdate(data):
    """ Envoie les données à la base RRD.
    """
    unixDate = time.mktime(time.strptime(str(data['timestamp']), "%Y%m%d%H%M%S"))
    if data['temp_in'] >= 69.9:
        data['temp_in'] = "U"
    if data['temp_out'] >= 69.9:
        data['temp_out'] = "U"
    if data['dewpoint'] >= 69.9:
        data['dewpoint'] = "U"
    if data['wind_chill'] >= 69.9:
        data['wind_chill'] = "U"
    if data['rel_hum_in'] <= 19 or data['rel_hum_in'] >= 96:
        data['rel_hum_in'] = "U"
    if data['rel_hum_out'] <= 19 or data['rel_hum_out'] >= 96:
        data['rel_hum_out'] = "U"
    if data['windspeed'] >= 150:
        data['windspeed'] = "U"
    values = "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s" % (int(unixDate), \
                                                   data['temp_in'], \
                                                   data['temp_out'], \
                                                   data['dewpoint'], \
                                                   data['wind_chill'], \
                                                   data['rel_hum_in'], \
                                                   data['rel_hum_out'], \
                                                   data['rel_pressure'], \
                                                   data['windspeed'], \
                                                   data['wind_angle'], \
                                                   data['rain_1h'])
    #print values
    rrdtool.update(rrdBaseName, values)



def makeTempGraph(graphName, periode, title):
    """ Génère un graph rrd pour la température.
    """
    rrdtool.graph(graphName,
                "--imgformat", "PNG",
                "--width", WIDTH,
                "--height", HEIGHT,
                "--start", "end-%s" % periode,
                "--title", "Température - %s" % title,
                "--vertical-label", "température (°C)",
                "--base", "1000",
                "DEF:ti_avg=%s:temp_in:AVERAGE" % RRD_FILENAME,
                "DEF:to_avg=%s:temp_out:AVERAGE" % RRD_FILENAME,
                "DEF:dp_avg=%s:dew_point:AVERAGE" % RRD_FILENAME,
                "DEF:wc_avg=%s:wind_chill:AVERAGE" % RRD_FILENAME,
                "LINE2:ti_avg#00AA00:Intérieure",
                "LINE2:wc_avg#FF00FF:Resentie",
                "LINE2:to_avg#FF0000:Extérieure",
                "LINE2:dp_avg#0000FF:Point de rosée",
                "HRULE:-5#8080FF",
                "HRULE:30#FF8080"
                )



def makeHumGraph(graphName, periode, title):
    """ Génère un graph rrd pour l'humidité.
    """
    rrdtool.graph(graphName,
                "--imgformat", "PNG",
                "--width", WIDTH,
                "--height", HEIGHT,
                "--start", "end-%s" % periode,
                "--title", "Humidité - %s" % title,
                "--vertical-label", "taux (%)",
                "--base", "1000",
                "--lower-limit", "20",
                "--upper-limit", "95",
                "--rigid",
                "DEF:hi_avg=%s:rel_hum_in:AVERAGE" % RRD_FILENAME,
                "DEF:ho_avg=%s:rel_hum_out:AVERAGE" % RRD_FILENAME,
                "LINE2:hi_avg#00AA00:Intérieure",
                "LINE2:ho_avg#FF0000:Extérieure",
                "HRULE:30#8080FF",
                "HRULE:80#FF8080"
                )



def makePressureGraph(graphName, periode, title):
    """ Génère un graph rrd pour la pression.
    """
    rrdtool.graph(graphName,
                "--imgformat", "PNG",
                "--width", WIDTH,
                "--height", HEIGHT,
                "--start", "end-%s" % periode,
                "--title", "Pression atmosphérique - %s" % title,
                "--vertical-label", "pression (hPa)",
                "--base", "1000",
                "--lower-limit", "1000",
                "--upper-limit", "1035",
                "--alt-y-grid",
                "--units-exponent", "1",
                "--rigid",
                "DEF:p_avg=%s:rel_pressure:AVERAGE" % RRD_FILENAME,
                "LINE2:p_avg#00AA00",
                "HRULE:1010#8080FF",
                "HRULE:1020#FF8080"
                )



def makeWindGraph(graphName, periode, title):
    """ Génère un graph rrd pour le vent.
    """
    rrdtool.graph(graphName,
                "--imgformat", "PNG",
                "--width", WIDTH,
                "--height", HEIGHT,
                "--start", "end-%s" % periode,
                "--title", "Vent, vitesse et direction - %s" % title,
                "--vertical-label", "vitesse (km/h)",
                "--base", "1000",
                "--lower-limit", "-3.5",
                "--upper-limit", "30",
                "--rigid",
                "DEF:ws_avg=%s:windspeed:AVERAGE" % RRD_FILENAME,
                "DEF:ws_max=%s:windspeed:MAX" % RRD_FILENAME,
                "DEF:ws_min=%s:windspeed:MIN" % RRD_FILENAME,
                "DEF:wa=%s:wind_angle:AVERAGE" % RRD_FILENAME,
                "CDEF:min2max=ws_max,ws_min,-",
                "CDEF:N=wa,22,GE,wa,wa,338,+,IF,337,362,LIMIT,360,/,FLOOR,3,-",
                "CDEF:NE=wa,22,68,LIMIT,360,/,FLOOR,3,-",
                "CDEF:E=wa,67,113,LIMIT,360,/,FLOOR,3,-",
                "CDEF:SE=wa,112,158,LIMIT,360,/,FLOOR,3,-",
                "CDEF:S=wa,157,203,LIMIT,360,/,FLOOR,3,-",
                "CDEF:SO=wa,202,238,LIMIT,360,/,FLOOR,3,-",
                "CDEF:O=wa,237,293,LIMIT,360,/,FLOOR,3,-",
                "CDEF:NO=wa,292,338,LIMIT,360,/,FLOOR,3,-",
                "AREA:ws_min#FFFFFF",
                "STACK:min2max#22FF22",
                "LINE2:ws_avg#00AA00",
                "AREA:N#FF0000:N  ",
                "AREA:NE#FF8800:NE ",
                "AREA:E#F0F000:E  ",
                "AREA:SE#C0F000:SE ",
                "AREA:S#00F0F0:S  ",
                "AREA:SO#0000FF:SO ",
                "AREA:O#A000FF:O  ",
                "AREA:NO#FF00FF:NO ",
                "HRULE:5#8888FF",
                "HRULE:20#FF8888"
                )



def makeRainGraph(graphName, periode, title):
    """ Génère un graph rrd pour la pluie.
    """
    rrdtool.graph(graphName,
                "--imgformat", "PNG",
                "--width", WIDTH,
                "--height", HEIGHT,
                "--start", "end-%s" % periode,
                "--title", "Pluie - %s" % title,
                "--vertical-label", "précipitations (mm)",
                "--base", "1000",
                "--lower-limit", "0",
                "--upper-limit", "5",
                "--rigid",
                "DEF:r_avg=%s:rain_1h:AVERAGE" % RRD_FILENAME,
                "LINE2:r_avg#00AA00",
                "HRULE:1#8080FF",
                "HRULE:3#FF8080"
                )



if __name__ == "__main__":
    while True:
        t = time.time()


        # Mise à jour base RRD
        config = ws2300.loadConfig()
        table = config['MYSQL']['table']
        request = "SELECT * FROM %s ORDER BY timestamp DESC LIMIT 1" % table
        data = ws2300.collect(request, fetch='one')
        try:
            rrdUpdate(data)
        except rrdtool.error, s:
            print s


        # Génèration des graphes
        for periode, graphName, title in (("30hours", "1d", "jour"),
                                        ("8days", "1w", "semaine"),
                                        ("32days", "1m", "mois"),
                                        ("13months", "1y", "année")
                                        ):
            fd, path = tempfile.mkstemp(".png", "weather_")
            makeTempGraph(path, periode, title)
            dst = os.path.join(GRAPH_PATH, "temp-%s.png" % graphName)
            shutil.move(path, dst)
            os.chmod(dst, stat.S_IRGRP+stat.S_IROTH),


            fd, path = tempfile.mkstemp(".png", "weather_")
            makeHumGraph(path, periode, title)
            dst = os.path.join(GRAPH_PATH, "hum-%s.png" % graphName)
            shutil.move(path, dst)
            os.chmod(dst, stat.S_IRGRP+stat.S_IROTH),


            fd, path = tempfile.mkstemp(".png", "weather_")
            makePressureGraph(path, periode, title)
            dst = os.path.join(GRAPH_PATH, "pressure-%s.png" % graphName)
            shutil.move(path, dst)
            os.chmod(dst, stat.S_IRGRP+stat.S_IROTH),


            fd, path = tempfile.mkstemp(".png", "weather_")
            makeWindGraph(path, periode, title)
            dst = os.path.join(GRAPH_PATH, "wind-%s.png" % graphName)
            shutil.move(path, dst)
            os.chmod(dst, stat.S_IRGRP+stat.S_IROTH),


            fd, path = tempfile.mkstemp(".png", "weather_")
            makeRainGraph(path, periode, title)
            dst = os.path.join(GRAPH_PATH, "rain-%s.png" % graphName)
            shutil.move(path, dst)
            os.chmod(dst, stat.S_IRGRP+stat.S_IROTH),


        # Attend la prochaine période (5min)
        time.sleep(5*60 - (time.time() - t))