Rapport quotidien de votre serveur et plus…

Bonjour visiteur du jour.

Au moyen d’une subtile recherche Google, vous venez vous perdre ici et tant pis pour vous 🙂

Au menu du jour, comment se faire un rapport en pdf sur l’état de santé de son serveur et le recevoir sur sa boite mail.

Regarder tous les jours, les beaux graphiques réalisés pour nous par domoticz ça va bien un moment. Recevoir des alertes par sms en cas de problème c’est du déjà vu.  Je recherchais le moyen de recevoir par mail un rapport en pdf sur l’état de santé (à un instant T) de mon serveur domoticz ainsi qu’un certain nombre d’informations utiles pour moi.

Les utilisateurs domoticz trouveront ici l’information sur la date et l’heure de la mise en route du service ainsi que son pid et la conso mémoire.

Je laisse libre à chacun de juger l’utilité de ce type de rapport. L’idée de ce partage est de permettre d’explorer de nouvelles pistes.

Le rapport est un document pdf, tramis par mail via des tâches planifiées (cron).

Rapport

Et c’est ainsi que depuis lundi, je reçois tous les matins ce petit rapport sur ma boite mail.

Dans la première partie, on retrouve des infos sur la mémoire, cpu, disque etc. Dans la seconde, je place des informations pratiques. D’ailleurs, si j’oublie de commander des granulés ça va être ma fête 🙂

ça marche comment ?

La partie système est mise en œuvre grâce au module psutil de python dont l’emploi le plus connu est le logiciel glances de Nicolargo.

Un script python lance des requêtes json au serveur domoticz pour la partie granulés, edf, batterie des modules z-wave.

Enfin, le pdf est créé grâce à la librairie fpdf

Le code du programme rapport.py

#!/usr/bin/env python
# -*- coding:Utf-8 -*-
#
# Ce programme python prépare, met en forme et envoi par mail un document pdf reprenant des informations du serveur domoticz
# Utilise les modules psutil, request fpdf
# Version 1 de février 2015 par José
#
# Basé sur le travail de Christophe CARON  http://www.caron.ws/ pour la partie supervision psutils https://github.com/giampaolo/psutil
# Utilise le module de recherche de Patrice du site easydomoticz.fr
# Le code de la partie mail vient du site http://astuces.absolacom.com/developpement/envoyer-un-mail-avec-pieces-jointes-en-python/
# Merci à eux.
# Les paramètres liés à domoticz se trouvent sur un fichier (config.py) situé dans le même répertoire
#
##########
#
# Il faut préalablement installer les modules suivants:
# installer python-pip
# par sudo apt-get install python-pip
#
# installer request
# sudo pip install requests
#
# installer psutils
# sudo pip install psutil
#
# installer fpdf
# sudo apt-get install pypdf
#
###########

from fpdf import FPDF
import data
import datetime
import sys
import config
import time
import requests

# Récupération et formatage de la date pour donner le nom du fichier
datejour = datetime.datetime.now()
datejour = datejour.strftime('%d-%m-%Y %H-%M-%S')
title=u"Rapport d'état du serveur Domoticz"

# Classe PDF de pypdf
class PDF(FPDF):
        def header(self):
                #Arial bold 15
                self.set_font('Arial','B',15)
                #Calculate width of title and position
                w=self.get_string_width(title)+6
                self.set_x((210-w)/2)
                #Colors of frame, background and text
                self.set_draw_color(0,0,204)
                self.set_fill_color(255,153,102)
                self.set_text_color(0,0,0)
                #Thickness of frame (1 mm)
                self.set_line_width(1)
                #Title avec logo
                self.image('img/logo.jpg',10,6,30);
                self.cell(w,9,title,1,1,'C',1)
                #Line break
                self.ln(10)

        def footer(self):
                #Position at 1.5 cm from bottom
                self.set_y(-15)
                #Arial italic 8
                self.set_font('Arial','I',8)
                #Text color in gray
                self.set_text_color(128)
                #Page number
                self.cell(0,10,'Rapport du '+ datejour + ' - P'+str(self.page_no()),0,0,'C')

        def chapter_title(self,num,label):
                #Arial 11
                self.set_font('Arial','',11)
                #Background color
                self.set_fill_color(255,255,255)
                #Title avec image du rapsberry pi
                self.cell(0,5,label,0,1,'L',1)
                self.image('img/pi.jpg',110,42,65);
                #Line break
                self.ln(2)

        def chapter_body(self,name):
                #Arial 11
                self.set_font('Arial','',11)
                #Output justified text
                self.multi_cell(0,5,name)
                #Line break
                self.ln()
                #Mention in italics
                self.set_font('','I')

        def print_chapter(self,num,title,name):
                self.chapter_title(num,title)
                self.chapter_body(name)

        def chapitre_general_titre(self,num,texte):
                #Arial 11
                self.set_font('Arial','',11)
                #Background color
                self.set_fill_color(255,255,255)
                # Placement suivant l'image
                if num == 20:
                        self.image('img/edf.jpg',10,135,20)
                        self.set_y(136)
                        self.set_x(36)
                        self.cell(0,5,texte,0,1,'L',1)

                if num == 21:
                        self.image('img/eo2.jpg',10,152,15)
                        self.set_y(153)
                        self.set_x(36)
                        self.cell(0,5,texte,0,1,'L',1)

                if num == 22:
                        self.image('img/cuve.jpg',10,187,20)
                        self.set_y(188)
                        self.set_x(36)
                        self.cell(0,5,texte,0,1,'L',1)

                if num == 23:
                        self.image('img/oregon.jpg',10,220,20)
                        self.set_y(220)
                        self.set_x(36)
                        self.cell(0,5,texte,0,1,'L',1)

                #Line break
                self.ln(2)
                self.set_x(36)

        def chapitre_general(self,texte):
                #Arial 11
                self.set_font('Arial','',11)
                #Background color
                self.set_fill_color(255,255,255)
                #Abcisse
                self.set_x(36)
                #Texte à mettre dans le pdf
                self.cell(0,5,texte,0,1,'L',1)
                #Line break
                self.ln(2)
                self.set_x(36)

# Module de recherche de Patrice
def recherche(idx, recherche, decal, nb_car):

        # URL Domoticz a interroger pour recuperer les infos est type=devices&rid=XXX

        json_url='/json.htm?type=devices&rid='
        requete='http://'+config.domoticz_ip+':'+config.domoticz_port+json_url+str(idx)

        r=requests.get (requete)
        ch= r.text
        lgterme=len(str(recherche))
        trouve_a= ch.find(str(recherche))
        debut=trouve_a+lgterme

        resultat=ch[debut+int(decal):debut+int(decal)+int(nb_car)]

        return resultat

# Lance les requêtes au moyen du programme collecte

# Récupération EDF
# recherche(idx,recherche,decal,nb_car)
edf=recherche('180', 'Data', '5', '4')

# Récupération du nombre de granulés en stock
# Calcul du nombre de sac par rapport à la variable du fichier config
granules=recherche('164', 'Counter', '5', '2')
humidite=recherche('171', 'Humidity', '4', '2')
stock=int(config.qte_granules_total) - int(granules)
poids=int(granules) * int(config.poids_sac_granules)

# Récupération du volume et de la hauteur de la cuve
volume=recherche('177', 'Counter', '5', '4')
hauteur=recherche('176', 'Data', '5', '3')
temp=recherche('101', 'Data', '5', '3')

# Récupération de l'état des batteries
batsdb=recherche('169', 'BatteryLevel', '4', '3')

# Création du PDF
pdf=PDF()
pdf.set_title(title)
pdf.set_author(u'José')
pdf.add_page()

# Mise en forme des données système
pdf.print_chapter(1,u'Information mémoire (Disponible ' + data.mpourcent + u" %)","Total = " + data.mtotal + u" - Utilisée = " + data.mutilise + " - Libre = " + data.mlibre)
pdf.print_chapter(2,u'Information mémoire swap (Utilisé ' + data.mspourcent + u" %)","Total = " + data.mstotal + u" - Utilisée = " + data.msutilise + " - Libre = " + data.mslibre)
pdf.print_chapter(3,u'Information CPU',"Charge = " + data.usagecpu + u" % - Température = "+str(data.cpu_temperature)+u" °C")
pdf.print_chapter(4,u'Espace disque carte SD (utilisée à '+ data.pourcent + "%)","Total = " + data.total + u" - Utilisé = " + data.utilise + " - Libre = " + data.libre)
pdf.print_chapter(5,u'Le module Domoticz (pid ' + str(data.pid) + ') fonctionne depuis le ' + str(data.boot) + ' - Status : ' + data.status,u'Ce soft utilise '+ str(data.mem) + u' de mémoire.')
pdf.print_chapter(6,u'Temps de fonctionnement du serveur : '+data.demarrage,'')

# Trace une ligne pour séparer les données système du reste
pdf.dashed_line(10,130,200,130,2,2)

# Mise en forme des données générales
# EDF
pdf.chapitre_general_titre(20,u"La valeur de la consommation EDF de la journée d'hier s'élève à " + edf + u" euros (hors abo).")

# Granulés
pdf.chapitre_general_titre(21,u"Il reste " + str(stock) + u" sacs de granulés en stock sur " + str(config.qte_granules_total) + '.')
pdf.chapitre_general(u"Représente une consommation de "+ str(granules) + u" sacs à ce jour, soit " + str(poids) + " kg." )
pdf.chapitre_general(u"Le niveau d'humidité ambiante du stockage est de " + humidite + u" %.")

# Ajoute un message d'alerte pour lancer la commande
if int(stock) < 20:
        # Place la couleur du texte en rouge
        pdf.set_text_color(204,0,0)
        pdf.chapitre_general(u"Attention le stock est trop bas. Il faut lancer une commande !")
        # Remet la couleur en noir
        pdf.set_text_color(0,0,0)

# Cuve
pdf.chapitre_general_titre(22,u'Le volume de la cuve est de '+ volume + " m3.")
pdf.chapitre_general(u"La hauteur d'eau est de " + hauteur + " cm.")
pdf.chapitre_general(u"La température de l'eau est de "+ temp + u"°C.")

# Batteries des sondes Oregon
pdf.chapitre_general_titre(23,u'Etat batterie sonde salle de bains: '+ batsdb + " %.")
pdf.chapitre_general(u"Etat batterie sonde cabane de jardin: "+ batsdb + " %.")
pdf.chapitre_general(u"Etat batterie sonde congélateur: "+ batsdb + " %.")

# Lancement de la création du rapport
pdf.output('Rapport.pdf','F')
rapport.py

Le programme d’envoi de mail

#!/usr/bin/env python
# -*- coding:Utf-8 -*-
#
# Récupération du code de la page
# http://astuces.absolacom.com/developpement/envoyer-un-mail-avec-pieces-jointes-en-python/
# Merci à son auteur
#
########

import smtplib
import os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

# Variables
files = ['Rapport.pdf'] # Pièces jointes avec leur chemin
destinataires = ['destinataire1@free.fr', 'destinataire2@free.fr'] # Mettre des [] Adresses mail séparées par des virgules
expediteur = 'expediteur@free.fr'
titre = u"Rapport journalier Domoticz"
message = u"Bonjour a tous, \nVoici votre rapport journalier du systeme domoticz. \nBonne journee."
smtp = 'smtp.free.fr'

def send_mail(send_from, send_to, subject, text, files=[], server='localhost'):

        assert type(send_to)==list
        assert type(files)==list
        msg = MIMEMultipart()
        msg['From'] = send_from
        msg['To'] = COMMASPACE.join(send_to)
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject
        msg.attach( MIMEText(text) )

        for f in files:
                part = MIMEBase('application', "octet-stream")
        #print "Transmission du mail avec la pièce jointe : " + f
        part.set_payload( open(f,"rb").read())
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))

        msg.attach(part)

        smtp = smtplib.SMTP(server)
        smtp.sendmail(send_from, send_to, msg.as_string())
        smtp.close()

# Module d'envoi de mail
send_mail(expediteur, destinataires, titre, message, files, smtp)
mail.py

Le programme de supervision data.py qui utilise la librairie psutil:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
#########
#
# Utilisation du travail de Christophe CARON
# http://www.caron.ws/
#
# Récupération des données pour le module rapport de domoticz
#
# Jose - Février 2015 -  Ajout de la partie domoticz
#
#########

import psutil
import os
import sys
import string
import datetime
from subprocess import PIPE, Popen
from datetime import timedelta

#convertion des unites en Ko,Go,To
def bytes2human(n):
    # http://code.activestate.com/recipes/578019
    # >>> bytes2human(10000)
    # '9.8K'
    # >>> bytes2human(100001221)
    # '95.4M'
    symbols = (' Ko', ' Mo', ' Go', ' To', ' Po', 'Eo', 'Zo', 'Yo')
    prefix = {}
    for i, s in enumerate(symbols):
        prefix[s] = 1 << (i+1)*10
    for s in reversed(symbols):
        if n >= prefix[s]:
            value = float(n) / prefix[s]
            return '%.1f%s' % (value, s)
    return "%sB" % n

# Lecture de la temperature
def get_cpu_temperature():
    process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE)
    output, _error = process.communicate()
    return float(output[output.index('=') + 1:output.rindex("'")])

# Détermine la date et l'heure du dernier reboot de domoticz
def domo():
        for p in psutil.process_iter():
                try:
                        pi = p.as_dict(attrs=['pid', 'name', 'create_time', 'memory_info', 'status'])
                except:
                        pass
                else:
                        if pi['name'] == 'domoticz':
                                pid = pi['pid']
                                #print 'Pid correspondant: ', pi['pid']
                                boot = datetime.datetime.fromtimestamp(pi['create_time']).strftime("%d-%m-%Y %H:%M:%S")
                                #print 'Heure de la mise en service domoticz', boot
                                mem = pi['memory_info'][0]+pi['memory_info'][1]
                                #print 'Mémoire :', mem
                                status = pi['status']
                                #print status

        return boot, pid, mem, status

# Uptime
with open('/proc/uptime', 'r') as f:
        uptime_seconds = round(float(f.readline().split()[0]),0)
        demarrage = str(timedelta(seconds = uptime_seconds))
        demarrage = demarrage.replace('days','Jours',1)
        demarrage = demarrage.replace(',',' et',1)
        demarrage = demarrage.replace('day','Jour',1)
        demarrage = demarrage.replace(':','h ',1)
        demarrage = demarrage.replace(':','mn ',1)
        demarrage = demarrage+ 's '

# Attribution des valeurs aux variables
# SD card
valeur = psutil.disk_usage('/')
part = psutil.disk_partitions(all=False)
infopart = (part[0])[2]        # extration de l'extension
total = bytes2human(valeur.total)
utilise = bytes2human(valeur.used)
libre = bytes2human(valeur.free)
pourcent = str(valeur.percent)

# CPU
usagecpu = str(psutil.cpu_percent(interval=1))
p = psutil.Process(os.getpid())

# Heure mise a jour
dateheure = datetime.datetime.now()
dateheure = dateheure.strftime('%d/%m/%Y')
#dateheure = datetime.datetime.fromtimestamp(p.create_time).strftime("%d-%m-%Y %H:%M")

# Temperature
cpu_temperature = get_cpu_temperature()
p = psutil.Process(os.getpid())

# Memoire Vive RAM
valeur = psutil.virtual_memory()
mtotal = bytes2human(valeur.total)
mdispo = bytes2human(valeur.available)
mutilise = bytes2human(valeur.used)
mlibre = bytes2human(valeur.free)
mpourcent = str(valeur.percent)

# Memoire SWAP
valeur = psutil.swap_memory()
mstotal = bytes2human(valeur.total)
msutilise = bytes2human(valeur.used)
mslibre = bytes2human(valeur.free)
mspourcent = str(valeur.percent)

# Date et heure de boot domoticz et pid système
boot, pid, mem, status = domo()

# Mise en forme de la mémoire
mem =  bytes2human(mem)

Maintenant que vous avez les sources, je détaille rapidement le contenu.

Les programmes data.py et config.py sont chargés comme modules du programme rapport.py. Ce dernier récupère toutes les données à mettre dans le rapport et procède à sa création grâce à la classe fpdf. Une tâche planifiée réalise l’opération puis transmet le rapport par mail (gare au spam, le blacklistage n’est pas loin).

Les images sont stockées dans un répertoire « img » afin que ça ne devienne pas le bazar.

Allez, je file commander mes granulés.

Si je suis allé trop vite, laissez un message. Je repasse de temps en temps.

 Sources et remerciements:

La partie supervision : Christophe Caron – http://www.caron.ws

La partie mail : Manuberro – http://astuces.absolacom.com/developpement/envoyer-un-mail-avec-pieces-jointes-en-python/

La requête domoticz : Patrice – http://easydomoticz.com

Projet domotique complet (fin)

Bonjour visiteur du soir ou du matin 🙂

Je dois depuis bien longtemps rédiger et publier mon petit projet domotique. Faute de temps et de courage, je me trouve toujours autre chose à faire.

Bon d’accord, je commence la rédac ce soir. Pour vous mettre l’eau à la bouche et avant de débuter cette série d’articles, j’aimerai vous montrer à quoi ressemble mon tableau de bord. La fin du projet en quelque sorte.

Et maintenant voilà qu’il nous parle de voiture…

Mais non pas de panique ! Il s’agit d’un point d’information qui permet en un seul coup d’œil, de connaitre tous les points qui me semble important dans la maison. Totalement inspiré du site magdiblog, brièvement décrit dans un précédent article, j’ai adapté le projet HOMEDASHSCREEN à mes besoins.

Voici le résultat:

DashBoard

Cette page web se trouve être la page par défaut de mon navigateur internet. Ainsi au premier coup d’oeil, je visualise l’heure, le flux rss (il s’agit du monde dans l’exemple), le nombre de visites du blog (okay jamais plus de 15 par jours).

Au centre, j’ai dessiné le plan de la maison avec les températures de toutes les pièces (rafraichissement toutes les 5 minutes). Les deux gauges à droite indiquent le niveau d’eau dans la cuve ainsi que la consommation électrique de la maison.

Lorsque le chauffage est en marche, sous le plan, apparait les zones de chauffe et enfin en bas à gauche sont listés les évènement d’un calendrier Google au format ical.

Merci encore aux utilisateurs du site magdiblog pour leur travail.

Hasta la vista 🙂

Supervision d’une cuve de recuperation d’eau

Bonjour à tous,

Dessin_cuveJ’aborde ici mon premier projet grandeur nature. Comme tout le monde, après avoir réussi à faire clignoter des diodes, il me fallait un véritable objectif pour mettre en pratique, grandeur nature, tout ce que j’avais eu l’occasion de tester.

Alors, l’année dernière à la sortie de l’hiver, je vérifie le volume d’eau contenu dans ma cuve enfouie de 2500 L.

Là, c’est le drame, il restait tout au plus 50 cm au fond. Me voilà partie en mode spéléo avec frontale et baladeuse à la recherche d’une fuite. Rien, nada 🙁

Je nettoie les filtres et guette la première averse, je suis enfin soulagé de voir que le niveau remonte. Il n’était pas question de rester aveugle et de se taper un démontage et levage de couvercle tous les 15 jours.

Il me faut l’aide de la technique ! En parcourant le NET, je découvre le Rasberry Pi et la communauté qui gravite autour.

Mon attention se porte particulièrement sur le blog d’Idelman.

Allez zou c’est parti, je bricole un truc en m’inspirant grandement du travail déjà fait histoire de ne par réinventer la roue.

Schéma de principe:

principeSchéma de raccordement des différents capteurs.

SchémaIdée de base :

Il me faut sur une petite page web permettant de visualiser:
– la hauteur d’eau,
– le volume estimé d’eau contenu,
– la température de l’eau,
– la température exterieure,
– la température de la boite de dérivation au cas où…

Elle doit également permettre de commander ma pompe de relevage et une prise de courant extérieure. Si l’interface vous dit quelque chose, c’est tout à fait normal. Elle est issue de la version qui précède le projet Yana-serveur d’Idelman.

mini_web

Pour visualiser les niveaux à partir du Web sans permettre un accès au serveur local, le raspberry de la cuve transmet toutes les 15 minutes, les graphiques sur ce site.

Eyesathome

On commence par où ?

une petite mise au point s’impose avant d’attaquer dans le dur….

Cette page n’est qu’un exemple de ce que j’ai mis en place chez moi. Les informations données ici n’ont pas d’autre but que d’aider ceux qui peuvent être intéressés par le sujet et remercier ceux qui m’ont inspirés.

Je vous rappelle les risques liés à la présence d’eau et du secteur (230 v).

Et enfin, dans la vie, je ne suis pas développeur, le code est brutal, peu adapté mais fonctionnel. J’ai depuis un peu progressé car j’ai une dizaine de capteurs de température dans toute la maison me permettant de gérer le chauffage mais ça c’est une autre histoire.

Le matos (liens donnés pour l’exemple):

Rasperry Pi (modèle B) installation classique avec OS raspbian,
– un capteur à ultrasons type HC-SR04,

hc– trois capteurs de température DS18B20,
– un module deux relais,

relais– une grosse boite de dérivation étanche pouvant contenir un module CPL + raspberry + un peu de bazar en plus :),
– une boite de dérivation 10*10 par exemple pouvant contenir le capteur à ultrasons,
– de la gaine thermo (pour faire le capteur de température immergé),
– des connecteurs RS232 pour raccorder les sondes de températures et le capteur HC-SR04.

rs232

Voici une image du rendu final

Db9Je ne reviens pas sur l’installation de l’os sur le raspberry, il existe une multitude de sites reprenant le sujet.

Les sondes de températures:

Elles utilisent le bus ONE WIRE en mode parasite comme indiqué sur ce site dont je recommande la lecture au passage. Vu le prix des sondes DS18B20 étanches, je vous invite à les faire vous même avec de la gaine thermo et votre fer à souder préféré comme indiqué ici.

sonde_eau

La sonde de profondeur:

Profondeur

Le capteur à ultrason type HC-SR04 se trouve dans une boite de dérivation percée aux dimensions des deux capteurs. Pour finaliser l’étanchéité, j’ai déposé un filet de silicone de salle de bains qui trainait au fond du garage. La boite est fixée sur un rail à placo qui repose sur le bord plastique de la cuve (en dessous de la réhausse). Les capteurs se trouvent à 18 cm de la hauteur maximum de l’eau.

Le réseau informatique:

J’ai testé les dongles wifi mais l’humidité ambiante finie par abîmer les connecteurs. J’ai opté pour un boitier CPLqui me restait. De toute façon, il faudra bien alimenter la pompe en 230 volts. L’adresse IP du lan est attribuée par un DHCP statique par l’intermédiaire de la box.

Au passage, j’attire votre ATTENTION sur les dangers du 230 V :

Si vous n’êtes pas à l’aise sur le sujet, je vous invite à prendre toutes les précautions qui s’imposent et en particulier,

COUPEZ LE COURANT avant toute intervention.

L’environnement où se trouve cette installation est plutôt humide, soyez prudent. Je décline toute responsabilité en cas d’accident.

Comment ça marche, ton affaire ?

Toutes les 5 minutes le script (capture.pl) collecte les températures des 3 sondes et les stock dans une base rrdtool. Puis toutes les 15 minutes, je transferts les images sur le site miroir en FTP.

Voici une vue du crontab qui tourne sur le serveur

# m h  dom mon dow   command
# Capture les temperatures par le bus 1-Wire
*/5 * * * * /home/super/programmes/temperatures/capture.pl

# Lance une copie des graphs sur le site de free toutes les 15 min
*/15 * * * * /home/super/programmes/syteme/copie_site.sh

# Lance les scripts lies a la hauteur d'eau et au volume
*/5 * * * * /home/super/programmes/profondeur/capa.py
*/6 * * * * /home/super/programmes/profondeur/capa.sh

# Lance les scripts de monitoring et graphiques
*/15 * * * * /usr/bin/python /home/super/programmes/temperatures/verif_tech.py
*/15 * * * * /usr/bin/python /home/super/programmes/temperatures/verif_cuve.py

Les scripts:

Les températures:

Comme indiqué plus haut, une base RRDTOOL nommée « temp_cuve.rrd » reçoit toutes les 5 minutes les valeurs des 3 sondes. Le script « creation_base_temp.sh » permet la création de la base RRDTOOL contenant les températures.

Comme vous pouvez le constatez dans les graphiques issus de cette base, les températures négatives ne s’affichent pas. Je modifierai cela plus tard.

rrdtool create temp_cuve.rrd --start N --step 300 \
DS:temp_eau:GAUGE:600:-5:20 \
DS:temp_ext:GAUGE:600:-25:45 \
DS:temp_tech:GAUGE:600:0:45 \
RRA:LAST:0.5:1:12 \
RRA:MAX:0.5:1:12 \
RRA:MIN:0.5:1:12 \
RRA:AVERAGE:0.5:1:12 \
RRA:AVERAGE:0.5:1:288 \
RRA:AVERAGE:0.5:12:168 \
RRA:AVERAGE:0.5:12:720 \
RRA:AVERAGE:0.5:288:365
creation_base_temp.sh

Cette base est alimentée toutes les 5 minutes par le script « capture.pl ». Il est en perl et j’avoue que l’année dernière je me suis contenté de l’adapter sans trop comprendre les rudiments du langage. Depuis, je me suis mis au python et ça va mieux 🙂

#!/usr/bin/perl
use LWP::UserAgent;

my $dir = '/home/super/programmes/temperatures/';
my $ua = new LWP::UserAgent;
$ua->timeout(120);
$modules = `cat /proc/modules`;

if ($modules =~ /w1_therm/ && $modules =~ /w1_gpio/)
{
#modules installed
}
else
{
$gpio = `sudo modprobe w1-gpio`;
$therm = `sudo modprobe w1-therm`;
}

# 1er capteur "eau"
$output = "";
$attempts = 0;
while ($output !~ /YES/g && $attempts < 5)
{
$output = `sudo cat /sys/bus/w1/devices/28-00000468dd1f/w1_slave 2>&1`;
if($output =~ /No such file or directory/)
{
print "Capteur cuve en panne.\n";
last;
}
elsif($output !~ /NO/g)
{
$output =~ /t=(\d+)/i;
$temp_eau = ($1 / 1000);
}

$attempts++;
}

# 2eme capteur "exterieur"
$output = "";
$attempts = 0;
while ($output !~ /YES/g && $attempts < 5)
{
$output = `sudo cat /sys/bus/w1/devices/28-00000468fd4a/w1_slave 2>&1`;
if($output =~ /No such file or directory/)
{
print "Capteur exterieur en panne.\n";
last;
}
elsif($output !~ /NO/g)
{
$output =~ /t=(\d+)/i;
$temp_ext = ($1 / 1000);
}

$attempts++;
}

# 3eme capteur "technique"
$output = "";
$attempts = 0;
while ($output !~ /YES/g && $attempts < 5)
{
$output = `sudo cat /sys/bus/w1/devices/28-0000049d7894/w1_slave 2>&1`;
if($output =~ /No such file or directory/)
{
print "Capteur technique en panne.\n";
last;
}
elsif($output !~ /NO/g)
{
$output =~ /t=(\d+)/i;
$temp_tech = ($1 / 1000);
$rrd = `/usr/bin/rrdtool update $dir/temp_cuve.rrd N:$temp_eau:$temp_ext:$temp_tech`;
}

$attempts++;
}

#print "Temperature eau: $temp_eau\n";
#print "Temperature exterieur: $temp_ext\n";
#print "Temperature boitier technique: $temp_tech\n";
Script de collecte des températures (capture.pl)

Bon c’est du brutal, y’a moyen de faire mieux !

Le script suivant lance la création des graphiques de températures à partir de la base rrdtool.Il est assez simple à personnaliser. On fixe au départ les répertoires sources, destination et les différentes couleurs. Cette partie du script (%.2lf) fixe le nombre de chiffres à afficher aprés la virgule.

#!/bin/bash
DIR="/home/super/programmes/temperatures"

# Pour le deplacement des fichiers img vers le repertoire du serveur web.
source='/home/super/programmes/temperatures/t_*.png'
destination='/var/www/cuve/img'
JOUR=$(date '+%d-%m-%Y %H-%M-%S')

# Affichage en degre C
TEMP_SCALE="Celsius"

#Choix des couleurs
TEMP_EAU_COUL="#000099" TEMP_TECH_COUL="#FF0000" TEMP_EXT_COUL="#993300"

#Titres  et informations
TITRE2="Suivi journalier" TITRE3="Suivi hebdomadaire" TITRE4="Suivi mensuel" TITRE5="Suivi annuel"

#Graphs heure multimesures
rrdtool graph $DIR/t_cuve_multi_4h.png --start -4h  --title="Vue globale sur 4 heures" --vertical-label=$TEMP_SCALE \
DEF:temp_eau=$DIR/temp_cuve.rrd:temp_eau:AVERAGE \
DEF:temp_ext=$DIR/temp_cuve.rrd:temp_ext:AVERAGE \
DEF:temp_tech=$DIR/temp_cuve.rrd:temp_tech:AVERAGE \
LINE1:temp_eau$TEMP_EAU_COUL:"Temperature de l'eau\n" \
LINE1:temp_ext$TEMP_EXT_COUL:"Temperature exterieure\n" \
LINE1:temp_tech$TEMP_TECH_COUL:"Temperature interne du boiter technique\n" \
COMMENT:" \n" \
GPRINT:temp_eau:LAST:"Mesure\: %.2lf" \
GPRINT:temp_eau:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_eau:MIN:"Mini\: %.2lf" \
GPRINT:temp_eau:MAX:"Maxi\: %.2lf\n" \
GPRINT:temp_ext:LAST:"Mesure\: %.2lf" \
GPRINT:temp_ext:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_ext:MIN:"Mini\: %.2lf" \
GPRINT:temp_ext:MAX:"Maxi\: %.2lf\n" \
GPRINT:temp_tech:LAST:"Mesure\: %.2lf" \
GPRINT:temp_tech:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_tech:MIN:"Mini\: %.2lf" \
GPRINT:temp_tech:MAX:"Maxi\: %.2lf\n" \
COMMENT:" \n" \
COMMENT:"Dernier releve $JOUR"

#Graphs par heure
rrdtool graph $DIR/t_eau_4h.png --start -4h  --title="Temperature eau sur 4 heures" --vertical-label=$TEMP_SCALE \
DEF:temp_eau=$DIR/temp_cuve.rrd:temp_eau:AVERAGE \
LINE1:temp_eau$TEMP_EAU_COUL:"Temperature de l'eau\n" \
GPRINT:temp_eau:LAST:"Mesure\: %.2lf" \
GPRINT:temp_eau:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_eau:MIN:"Mini\: %.2lf" \
GPRINT:temp_eau:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_ext_4h.png --start -4h --title="Temperature exterieure sur 4 heures" --vertical-label=$TEMP_SCALE \
DEF:temp_ext=$DIR/temp_cuve.rrd:temp_ext:AVERAGE \
LINE1:temp_ext$TEMP_EXT_COUL:"Temperature exterieure\n" \
GPRINT:temp_ext:LAST:"Mesure\: %.2lf" \
GPRINT:temp_ext:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_ext:MIN:"Mini\: %.2lf" \
GPRINT:temp_ext:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_tech_4h.png --start -4h --title="Temperature B.tech sur 4 heures" --vertical-label=$TEMP_SCALE \
DEF:temp_tech=$DIR/temp_cuve.rrd:temp_tech:AVERAGE \
LINE1:temp_tech$TEMP_TECH_COUL:"Temperature interne du boiter technique\n" \
GPRINT:temp_tech:LAST:"Mesure\: %.2lf" \
GPRINT:temp_tech:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_tech:MIN:"Mini\: %.2lf" \
GPRINT:temp_tech:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

#Graphs par jour
rrdtool graph $DIR/t_eau_24h.png --start -1d --title="Temperature eau sur 24 heures" --vertical-label=$TEMP_SCALE \
DEF:temp_eau=$DIR/temp_cuve.rrd:temp_eau:AVERAGE \
LINE1:temp_eau$TEMP_EAU_COUL:"Temperature de l'eau\n" \
GPRINT:temp_eau:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_eau:MIN:"Mini\: %.2lf" \
GPRINT:temp_eau:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_ext_24h.png --start -1d --title="Temperature exterieure sur 24 heures" --vertical-label=$TEMP_SCALE \
DEF:temp_ext=$DIR/temp_cuve.rrd:temp_ext:AVERAGE \
LINE1:temp_ext$TEMP_EXT_COUL:"Temperature exterieure\n" \
GPRINT:temp_ext:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_ext:MIN:"Mini\: %.2lf" \
GPRINT:temp_ext:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_tech_24h.png --start -1d --title="Temperature B.tech sur 24 heures" --vertical-label=$TEMP_SCALE \
DEF:temp_tech=$DIR/temp_cuve.rrd:temp_tech:AVERAGE \
LINE1:temp_tech$TEMP_TECH_COUL:"Temperature interne du boiter technique\n" \
GPRINT:temp_tech:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_tech:MIN:"Mini\: %.2lf" \
GPRINT:temp_tech:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

#Graphs par semaine
rrdtool graph $DIR/t_eau_1w.png --start -1w --title="Temperature eau sur 1 semaine" --vertical-label=$TEMP_SCALE \
DEF:temp_eau=$DIR/temp_cuve.rrd:temp_eau:AVERAGE \
LINE1:temp_eau$TEMP_EAU_COUL:"Temperature de l'eau\n" \
GPRINT:temp_eau:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_eau:MIN:"Mini\: %.2lf" \
GPRINT:temp_eau:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_ext_1w.png --start -1w --title="Temperature exterieure sur 1 semaine" --vertical-label=$TEMP_SCALE \
DEF:temp_ext=$DIR/temp_cuve.rrd:temp_ext:AVERAGE \
LINE1:temp_ext$TEMP_EXT_COUL:"Temperature exterieure\n" \
GPRINT:temp_ext:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_ext:MIN:"Mini\: %.2lf" \
GPRINT:temp_ext:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_tech_1w.png --start -1w --title="Temperature B.tech sur 1 semaine" --vertical-label=$TEMP_SCALE \
DEF:temp_tech=$DIR/temp_cuve.rrd:temp_tech:AVERAGE \
LINE1:temp_tech$TEMP_TECH_COUL:"Temperature interne du boiter technique\n" \
GPRINT:temp_tech:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_tech:MIN:"Mini\: %.2lf" \
GPRINT:temp_tech:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

#Graphs par mois
rrdtool graph $DIR/t_eau_1m.png --start -1m --title="Temperature eau sur 1 mois" --vertical-label=$TEMP_SCALE \
DEF:temp_eau=$DIR/temp_cuve.rrd:temp_eau:AVERAGE \
LINE1:temp_eau$TEMP_EAU_COUL:"Temperature de l'eau\n" \
GPRINT:temp_eau:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_eau:MIN:"Mini\: %.2lf" \
GPRINT:temp_eau:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_ext_1m.png --start -1m --title="Temperature exterieure sur 1 mois" --vertical-label=$TEMP_SCALE \
DEF:temp_ext=$DIR/temp_cuve.rrd:temp_ext:AVERAGE \
LINE1:temp_ext$TEMP_EXT_COUL:"Temperature exterieure\n" \
GPRINT:temp_ext:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_ext:MIN:"Mini\: %.2lf" \
GPRINT:temp_ext:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_tech_1m.png --start -1m --title="Temperature B.tech sur 1 mois" --vertical-label=$TEMP_SCALE \
DEF:temp_tech=$DIR/temp_cuve.rrd:temp_tech:AVERAGE \
LINE1:temp_tech$TEMP_TECH_COUL:"Temperature interne du boiter technique\n" \
GPRINT:temp_tech:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_tech:MIN:"Mini\: %.2lf" \
GPRINT:temp_tech:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

#Graphs 6 mois
rrdtool graph $DIR/t_eau_6m.png --start -25w --title="Temperature eau sur 6 mois" --vertical-label=$TEMP_SCALE \
DEF:temp_eau=$DIR/temp_cuve.rrd:temp_eau:AVERAGE \
LINE1:temp_eau$TEMP_EAU_COUL:"Temperature de l'eau\n" \
GPRINT:temp_eau:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_eau:MIN:"Mini\: %.2lf" \
GPRINT:temp_eau:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_ext_6m.png --start -25w --title="Temperature exterieure sur 6 mois" --vertical-label=$TEMP_SCALE \
DEF:temp_ext=$DIR/temp_cuve.rrd:temp_ext:AVERAGE \
LINE1:temp_ext$TEMP_EXT_COUL:"Temperature exterieure\n" \
GPRINT:temp_ext:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_ext:MIN:"Mini\: %.2lf" \
GPRINT:temp_ext:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_tech_6m.png --start -25w --title="Temperature B.tech sur 6 mois" --vertical-label=$TEMP_SCALE \
DEF:temp_tech=$DIR/temp_cuve.rrd:temp_tech:AVERAGE \
LINE1:temp_tech$TEMP_TECH_COUL:"Temperature interne du boiter technique\n" \
GPRINT:temp_tech:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_tech:MIN:"Mini\: %.2lf" \
GPRINT:temp_tech:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

#Graphs annuels
rrdtool graph $DIR/t_eau_1y.png --start -1y --title="Temperature eau sur 1 an" --vertical-label=$TEMP_SCALE \
DEF:temp_eau=$DIR/temp_cuve.rrd:temp_eau:AVERAGE \
LINE1:temp_eau$TEMP_EAU_COUL:"Temperature de l'eau\n" \
GPRINT:temp_eau:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_eau:MIN:"Mini\: %.2lf" \
GPRINT:temp_eau:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_ext_1y.png --start -1y --title="Temperature exterieure sur 1 an" --vertical-label=$TEMP_SCALE \
DEF:temp_ext=$DIR/temp_cuve.rrd:temp_ext:AVERAGE \
LINE1:temp_ext$TEMP_EXT_COUL:"Temperature exterieure\n" \
GPRINT:temp_ext:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_ext:MIN:"Mini\: %.2lf" \
GPRINT:temp_ext:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/t_tech_1y.png --start -1y --title="Temperature B.tech sur 1 an" --vertical-label=$TEMP_SCALE \
DEF:temp_tech=$DIR/temp_cuve.rrd:temp_tech:AVERAGE \
LINE1:temp_tech$TEMP_TECH_COUL:"Temperature interne du boiter technique\n" \
GPRINT:temp_tech:AVERAGE:"Moy\: %.2lf" \
GPRINT:temp_tech:MIN:"Mini\: %.2lf" \
GPRINT:temp_tech:MAX:"Maxi\: %.2lf" \
COMMENT:"Dernier releve $JOUR"

#Copie les graphs dans le repertoire du site local /var/www/cuve/img
#transfert.sh

#Transfert des donnees sur le serveur Web
chown www-data:www-data $source
sudo mv $source $destination
creation_graph.sh

Pour des raisons de sécurité, je ne voulais pas mettre mon raspberry pi directement sur le net. J’ai pris l’option de transférer les données (images) sur une pauvre page web consultable de partout. Le script pousse les images toutes les 15 minutes.

#! /bin/bash

######  Variables #############
TARGET_FTP="/var/www/cuve/img/ /img"
FTP="ftpperso.free.fr" LOGIN="#######" PASS="########"
MAIL="#######@free.fr" JOUR=$(date '+%d-%m-%Y %H-%M-%S')
#################################

# Balance les fichier sur le ftp free
lftp -e "open -u $LOGIN,$PASS $FTP; mirror -n -R $TARGET_FTP ;
bye";
# Message mail automatique
#echo "Mise a jour du site = ok" $JOUR | mail -s "Eyes At Home" $MAIL;
# Log de confirmation
#echo "Copie des fichiers et envoi de mail a "$JOUR >>/var/log/transfert.log;
copie_site.sh

La profondeur:

Le script se nomme capa.py. Il se lance en tâche planifiée toutes les 5 minutes. Comme pour les températures les données sont transmises à une base RRDTOOL. Le capteur doit être raccordé sur les pins 17 et 23 (que vous pouvez adapter à votre guise sous réserve de modifier les paramètres dans le script).

GPIO_TRIGGER = 17
GPIO_ECHO = 23

J’utilise encore une base rrdtool pour le stockage des données. La base créée se nomme capa_cuve.rrd.

rrdtool create capa_cuve.rrd --start N --step 300 \
DS:haut:GAUGE:600:1:130 \
DS:capa:GAUGE:600:0:2600 \
RRA:LAST:0.5:1:12 \
RRA:MAX:0.5:1:12 \
RRA:MIN:0.5:1:12 \
RRA:AVERAGE:0.5:1:12 \
RRA:LAST:0.5:1:288 \
RRA:MAX:0.5:1:288 \
RRA:MIN:0.5:1:288 \
RRA:AVERAGE:0.5:1:288 \
RRA:LAST:0.5:12:168 \
RRA:MAX:0.5:12:168 \
RRA:MIN:0.5:12:168 \
RRA:AVERAGE:0.5:12:168 \
RRA:LAST:0.5:12:720 \
RRA:MAX:0.5:12:720 \
RRA:MIN:0.5:12:720 \
RRA:AVERAGE:0.5:12:720 \
RRA:LAST:0.5:288:365 \
RRA:MAX:0.5:288:365 \
RRA:MIN:0.5:288:365 \
RRA:AVERAGE:0.5:288:365
creation_base.sh

Le script suivant a subi une modification. A l’origine, il est extrait d’ici |R|a|s|p|b|e|r|r|y|P|i|-|S|p|y|.|c|o|.|u|k| par Matt Hawkins. Repris par beaucoup d’entre nous, il offre un bon apprentissage de la sonde. Pour ma part, il me permet de déterminer la hauteur d’eau se trouvant dans la cuve et estimer son volume par calcul.
Je ne suis pas à 20 litres prés, l’estimation est suffisante.

#!/usr/bin/python
#+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#|R|a|s|p|b|e|r|r|y|P|i|-|S|p|y|.|c|o|.|u|k|
#+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#
# ultrasonic_1.py
# Measure distance using an ultrasonic module
#
# Author 1ere partie: Matt Hawkins
# Date   : 09/01/2013
# Author 2eme partie: Jose
# Date   : 10/05/2013

# Import required Python libraries
import time
import RPi.GPIO as GPIO
import rrdtool
import datetime

# Use BCM GPIO references
# instead of physical pin numbers
GPIO.setmode(GPIO.BCM)

# Define GPIO to use on Pi
GPIO_TRIGGER = 17
GPIO_ECHO = 23

# Set pins as output and input
GPIO.setup(GPIO_TRIGGER,GPIO.OUT)  # Trigger
GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo

# Set trigger to False (Low)
GPIO.output(GPIO_TRIGGER, False)

# Allow module to settle
time.sleep(0.5)

# Send 10us pulse to trigger
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
start = time.time()
while GPIO.input(GPIO_ECHO)==0:
start = time.time()

while GPIO.input(GPIO_ECHO)==1:
stop = time.time()

# Calculate pulse length
elapsed = stop-start

# Distance pulse travelled in that time is time
# multiplied by the speed of sound (cm/s)
distance = elapsed * 34300

# That was the distance there and back so halve the value
distance = distance / 2

# Mesure de la hauteur d'eau en faisant la différence entre la hauteur cuve pleine et le capteur 18 cm
fond=131.5
distance = fond - distance

# Fonction de calcul du volume théorique de la cuve
largeur=100
longueur=210

vol = largeur * longueur * distance
volume = vol / 1000

# Décoche les commentaires pour consulter les logs
print  "%.0f" % distance+" "+"%.0f" % volume

#Transfert dans la base rrdtool
database_file = "/home/super/programmes/profondeur/capa_cuve.rrd"
rrdtool.update(database_file, "N:%.2f" % distance+":%.0f" % volume)

# Reset GPIO settings
GPIO.cleanup()
capa.py

Quelques explications sur la mesure. Le script mesure le temps que met l’écho a revenir. J’ai pris le temps de mesurer la hauteur d’eau lorsque la cuve était pleine. Le capteur à ultrason se trouve dirigé vers la surface de l’eau et à une hauteur de 17 cm. Aprés la mesure, je retire la hauteur théorique pleine. Après un petit calcul de volume, j’estime la capacité en eau de la cuve.
On continue avec un script qui génère des graphiques.

#!/bin/bash
DIR="/home/super/programmes/profondeur"

# Pour le deplacement des fichiers img vers le repertoire du serveur web.
source='/home/super/programmes/profondeur/*_cuve_*.png'
destination='/var/www/cuve/img'
JOUR=$(date '+%d-%m-%Y %H-%M-%S')

# Affichage en degre C
ECHELLE="cm"
VOLUME="litres"

#Choix des couleurs
COUL_ECHELLE="#000099" COUL_VOLUME="#FF0000"

#Graphs par heure
rrdtool graph $DIR/h_cuve_4h.png --start -4h --title="Hauteur d'eau sur 4 heures" --vertical-label="cm"  \
DEF:haut=$DIR/capa_cuve.rrd:haut:AVERAGE \
LINE1:haut$COUL_ECHELLE:"Hauteur d'eau en $ECHELLE\n" \
GPRINT:haut:LAST:"Mesure\: %.0lf" \
GPRINT:haut:AVERAGE:"Moy\: %.0lf" \
GPRINT:haut:MIN:"Mini\: %.0lf" \
GPRINT:haut:MAX:"Maxi\: %.0lf" \
COMMENT:" \n" \
COMMENT:"Dernier releve $JOUR"

rrdtool graph $DIR/v_cuve_4h.png --start -4h --title="Volume sur 4 heures" --vertical-label="Litres" \
DEF:capa=$DIR/capa_cuve.rrd:capa:AVERAGE \
LINE1:capa$COUL_VOLUME:"Volume de la cuve en $VOLUME\n" \
GPRINT:capa:LAST:"Mesure\: %.0lf" \
GPRINT:capa:AVERAGE:"Moy\: %.0lf" \
GPRINT:capa:MIN:"Mini\: %.0lf" \
GPRINT:capa:MAX:"Maxi\: %.0lf" \
COMMENT:" \n" \
COMMENT:"Derniere estimation $JOUR"

#Graphs par jour
rrdtool graph $DIR/h_cuve_24h.png --start -1d --title="Hauteur d'eau sur 24 heures" --vertical-label="cm"  \
DEF:haut=$DIR/capa_cuve.rrd:haut:AVERAGE \
LINE1:haut$COUL_ECHELLE:"Hauteur d'eau en $ECHELLE\n" \
GPRINT:haut:AVERAGE:"Moy\: %.0lf" \
GPRINT:haut:MIN:"Mini\: %.0lf" \
GPRINT:haut:MAX:"Maxi\: %.0lf" \

rrdtool graph $DIR/v_cuve_24h.png --start -1d --title="Volume sur 24 heures" --vertical-label="Litres" \
DEF:capa=$DIR/capa_cuve.rrd:capa:AVERAGE \
LINE1:capa$COUL_VOLUME:"Volume de la cuve en $VOLUME\n" \
GPRINT:capa:AVERAGE:"Moy\: %.0lf" \
GPRINT:capa:MIN:"Mini\: %.0lf" \
GPRINT:capa:MAX:"Maxi\: %.0lf" \

#Graphs par semaine
rrdtool graph $DIR/h_cuve_1w.png --start -1w --title="Hauteur d'eau sur 1 semaine" --vertical-label="cm" \
DEF:haut=$DIR/capa_cuve.rrd:haut:AVERAGE \
LINE1:haut$COUL_ECHELLE:"Hauteur d'eau en $ECHELLE\n" \
GPRINT:haut:AVERAGE:"Moy\: %.0lf" \
GPRINT:haut:MIN:"Mini\: %.0lf" \
GPRINT:haut:MAX:"Maxi\: %.0lf" \

rrdtool graph $DIR/v_cuve_1w.png --start -1w --title="Volume sur 1 semaine" --vertical-label="Litres" \
DEF:capa=$DIR/capa_cuve.rrd:capa:AVERAGE \
LINE1:capa$COUL_VOLUME:"Volume de la cuve en $VOLUME\n" \
GPRINT:capa:AVERAGE:"Moy\: %.0lf" \
GPRINT:capa:MIN:"Mini\: %.0lf" \
GPRINT:capa:MAX:"Maxi\: %.0lf" \

#Graphs par mois
rrdtool graph $DIR/h_cuve_1m.png --start -1m  --title="Hauteur d'eau sur 1 mois" --vertical-label="cm" \
DEF:haut=$DIR/capa_cuve.rrd:haut:AVERAGE \
LINE1:haut$COUL_ECHELLE:"Hauteur d'eau en $ECHELLE\n" \
GPRINT:haut:AVERAGE:"Moy\: %.0lf" \
GPRINT:haut:MIN:"Mini\: %.0lf" \
GPRINT:haut:MAX:"Maxi\: %.0lf" \

rrdtool graph $DIR/v_cuve_1m.png --start -1m  --title="Volume sur 1 mois" --vertical-label="Litres" \
DEF:capa=$DIR/capa_cuve.rrd:capa:AVERAGE \
LINE1:capa$COUL_VOLUME:"Volume de la cuve en $VOLUME\n" \
GPRINT:capa:AVERAGE:"Moy\: %.0lf" \
GPRINT:capa:MIN:"Mini\: %.0lf" \
GPRINT:capa:MAX:"Maxi\: %.0lf" \

#Graphs pour 6 mois
rrdtool graph $DIR/h_cuve_6m.png --start -25w  --title="Hauteur d'eau sur 6 mois" --vertical-label="cm" \
DEF:haut=$DIR/capa_cuve.rrd:haut:AVERAGE \
LINE1:haut$COUL_ECHELLE:"Hauteur d'eau en $ECHELLE\n" \
GPRINT:haut:AVERAGE:"Moy\: %.0lf" \
GPRINT:haut:MIN:"Mini\: %.0lf" \
GPRINT:haut:MAX:"Maxi\: %.0lf" \

rrdtool graph $DIR/v_cuve_6m.png --start -25w  --title="Volume sur 6 mois" --vertical-label="Litres" \
DEF:capa=$DIR/capa_cuve.rrd:capa:AVERAGE \
LINE1:capa$COUL_VOLUME:"Volume de la cuve en $VOLUME\n" \
GPRINT:capa:AVERAGE:"Moy\: %.0lf" \
GPRINT:capa:MIN:"Mini\: %.0lf" \
GPRINT:capa:MAX:"Maxi\: %.0lf" \

#Graphs par an
rrdtool graph $DIR/h_cuve_1y.png --start -1y  --title="Hauteur d'eau sur 1 an" --vertical-label="cm" \
DEF:haut=$DIR/capa_cuve.rrd:haut:AVERAGE \
LINE1:haut$COUL_ECHELLE:"Hauteur d'eau en $ECHELLE\n" \
GPRINT:haut:AVERAGE:"Moy\: %.0lf" \
GPRINT:haut:MIN:"Mini\: %.0lf" \
GPRINT:haut:MAX:"Maxi\: %.0lf" \

rrdtool graph $DIR/v_cuve_1y.png --start -1y  --title="Volume sur 1 an" --vertical-label="Litres" \
DEF:capa=$DIR/capa_cuve.rrd:capa:AVERAGE \
LINE1:capa$COUL_VOLUME:"Volume de la cuve en $VOLUME\n" \
GPRINT:capa:AVERAGE:"Moy\: %.0lf" \
GPRINT:capa:MIN:"Mini\: %.0lf" \
GPRINT:capa:MAX:"Maxi\: %.0lf" \

#Transfert des données sur le serveur Web
chown www-data:www-data $source
sudo mv $source $destination
creation_graphs.sh

La page Web:

Basée sur le travail d’Idleman, la page de gestion est issue d’ici. Elle est tributaire de l’installation préalable d’un serveur apache ou autre. Si vous suivez les tutos d’Idleman depuis le début, cela ne devrait pas poser de problème. Bien entendu, vous pouvez installer votre serveur web préféré.

Une action sur le lien de page met en route la pompe de relevage ou la prise électrique qui sont commandées par l’intermédiaire de la carte aux deux relais. La page de configuration, vous permet de choisir les GPIO qui commanderont le ou les relais.

L’insertion des différents graphiques se fait par l’intermédiaire de balises <img> qui pointent sur le répertoire contenant les graphiques.

Et maintenant:

J’ai certainement oublié des choses ou je suis passé un peu vite sur certaines explications. Cette page et ces sous rubriques me permettent de garder en mémoire les scripts utilisés et les schémas. Vous l’avez certainement compris, ils ne sont pas tellement finalisés et doivent faire frissonner les puristes j’en suis conscient.

Bilan et évolutions:

Depuis un an, ce raspberry se trouve dans la cuve. Malgré l’environnement, il fonctionne très bien parfois mieux que celui que je maltraite sur mon bureau. 🙂

J’ai eu chaud à l’automne dernier car lors d’un violent orage, le trop plein de la cuve n’arrivait pas à tout absorber. C’est un peu normal car la totalité des eaux provenant de la toiture se déversent dedans. Je voyais le niveau d’eau monter et malgré la mise en route de la pompe immergée, l’eau à fini par noyer le capteur.
Après quelques jours de séchage, il a repris du service comme à la manœuvre.

Dans les évolutions futures, je pense remplacer le raspberry de la cuve par un arduino. Le fonctionnement serait sensiblement identique. Les deux appareils seraient raccordés par une liaison I2C car la liasion série est déjà utilisée sur un autre serveur qui collecte les données provenant du compteur EDF. Ceci me permettrait de récupérer un raspberry à brève échéance.

i2c_Bus

Le développement de mon nouveau projet est finalisé. Dés que j’aurai un peu de temps, je m’occuperai de sa rédaction et j’aurais le plaisir de vous retrouver ici.

 

Les sources:

Un grand merci à :

http://arduino103.blogspot.fr/
http://forum.pcinpact.com/topic/165594-raspberry-pi-fabriquons-des-trucs/
http://blog.idleman.fr/
http://www.manuel-esteban.com/
http://smhteam.info/blog/2011/11/15/faire-un-capteur-de-niveau-pour-une-cuve-deau/

Pleins d’autres sources ici

Avec une mention particulière au magasin en ligne http://shop.mchobby.be/fr/ qui grâce à ses traductions et à l’investissement personnel de son auteur nous font grandement progresser.

Augmenter le nombre de capteurs du bus one-wire.

Bonjour,

Si tout comment moi, vous aimez utiliser les capteurs DS18B20 ds18b20pour mesurer les températures de votre environnement, vous avez certainement atteint les limites des 10 capteurs possibles sur le bus one-wire (GPIO4) de votre rapsberry pi.

Et oui, le module w1-gpio est limité à 10 capteurs alors qu’en théorie le nombre de capteurs sur un bus one-wire est quasi illimité.

La solution m’a été apporté par Rinty lors d’un échange sur le site http://www.framboise314.fr/mesure-de-temperature-1-wire-ds18b20-avec-le-raspberry-pi/ que l’on ne présente plus.

Pour dépasser la limite, il suffit de créer un fichier wire.conf dans /etc/modprobe.d/
Vous écrivez à l’intérieur « options wire max_slave_count=20 » (sans les guillemets).

Après un reboot, comme par magie, le nombre max de capteurs est passé de 10 à 20.

Elle est pas belle la vie 🙂

Mon projet domotique (le matériel)

Bonjour visiteur de passage.

Dans une premier temps, je détaillerai la liste du matériel nécessaire au projet annoncé lors d’un article précédent. Puis, je présenterai un schéma de principe.

  • Un raspberry pi modèle B avec carte SD 8G classe 10.

raspberry-pi-model-b

  • Dix capteurs de température de type DS18B20 (un pour chaque pièce dans mon cas).ds18b20
  • Un afficheur LCD I2C de 20*4.

lcd_i2c

  • Des résistances.
  • Un composant permettant d’étendre le bus I2C P82B715PN.

P82B715

  • Un optocoupleur SFH620A permet la télérelève EDF via le port série.

sfh620a

  • Un pi cobbler pour assurer la liaison entre le raspberry et le circuit.

Adafruit_Pi_Cobbler_Breakout_Kit

  • Une série de relais permettant de commande le fil pilote des zones de chauffage et les ouvertures de portes (garage et portail).

relais

J’utilise également une alimentation 5 volts différentes pour tous les circuits de commandes évitant ainsi de trop tirer sur les ports GPIO et le rapsberry pi en général.

  • Une alimentation 5 volts 2 ampères

alimentation5v

  • Un interrupteur à souder.
  • Une diode Led rouge (au choix) pour la présence secteur.
  • Une diode 1N4148.

J’en profite pour remercier le père de mon collègue Nico qui, ancien prof de techo, m’a donné un stock énorme de composants électroniques 🙂

Voici le schéma de principe de l’installation.

Eyesathome

That’s all folks 🙂