Domoticz – Gérer sa consommation de granulés

Bonjour visiteur de passage,

Aujourd’hui, je partage ma gestion personnelle de la consommation en granulés de mon poêl Rika Como au moyen de domoticz et de mon karotz.

Tout un programme…

karotzCe dernier ne fait pas grand chose en ce moment. Il était temps pour lui d’arrêter de glander et de me regarder avec son ventre clignotant. Je ne vais pas ici vous faire découvrir ce qu’est un karotz mais sachez que s’il vous encombre, il existe une solution pour lui donner une nouvelle vie Openkarotz.

Bref, je chauffe une grande partie de la maison avec un poêle Rika Como. Depuis 2010, il marche parfaitement bien mais surtout il ne fait pas de bruit. rika

eo2Je stocke des sacs de 15 kg livrés par palette de 66 sacs.

Contrairement à belle maman qui note tout, je n’avais aucune idée de la quantité de granulés restants en stock dans la cabane de jardin. Alors, au lieu d’avoir sur une petite feuille de papier (vouée à être perdue corps et âme) le nombre de sacs engloutis par le poêle, j’ai décidé de faire la gestion par domoticz.

Le principe est le suivant:

Je passe un tag rfid devant le lapin. Lorsqu’il n’est pas trop débordé ^^, il lance une requête à destination d’un scénario de domoticz  « Ajout granulés ».

ajout

Le script récupère la valeur du compteur de granulés, l’incrémente de 1 (je compte par sac) et remet à jour le compteur. Le lapin m’annonce la quantité de sacs restants et l’équivalent en kg de la quantité consommé avec sa petite voix et enfin, je reçois un sms m’indiquant les mêmes informations. Tout ça est sensé éviter de tomber en panne de sacs… Mais je vous rassure comme tout bonhomme qui se respecte j’ai encore oublié d’en commander.

Allo Belle maman….

granulés

Le chiffre en haut se met à jour automatiquement après quelques minutes.

Val : 61 correspond au nombre de sacs consommés.

Prérequis:

Le karotz fonctionne sous openkarotz et dispose d’un flatnoz  flatnozprogrammé pour envoyer une url.

rfid

Le point important c’est l’URL. Mettez ici l’url json en remplaçant le caractère & par son équivalent en %26. Par exemple: (à adapter)

http://192.168.2.32:8080/json.htm?type=command%26param=switchlight%26idx=49%26switchcmd=On

En cas de problème, je pourrais faire un topo dessus.

La suite

Je dispose d’un fichier de configuration comprenant toutes les adresses ip et autres valeurs communes (quantité de sacs, poids, adresse ip et port de domoticz). Ce fichier fait partie des « import » appelé au début du script principal. En partique, il est situé dans le même répertoire que le script.

Voici un extrait:

#!/usr/bin/python
# -*-coding:Utf-8 -*
# José - Janvier 2015

# Module contenant toutes les variables Karotz
karotz_ip='192.168.10.113'
karotz_voip='alice'

# Module contenant toutes les variables Domoticz
domoticz_ip='192.168.10.120'
domoticz_port='8080'
domoticz_ident='XXXXX'
domoticz_passwd='ZZZZZ'

# Identifiants SMS Free mobile José
user = 'user'
pas = 'password'

# Phrases types température
texte_lu='Je viens de relever la température '
texte_liaison=' .Il y fait '
texte_fin='degrés.'

# Messages SMS
sms_chauffeau_off = 'Le chauffe-eau est en service.'
sms_chauffeau_on = 'L\'alimentation électrique du chauffe-eau est coupée.'

sms_ordi_romain_on= 'Le PC portable de Romain est connecté au réseau wifi.'
sms_ordi_romain_off= 'Le PC portable de Romain n\'est plus sur le réseau wifi.'

# IDX des widgets domoticz
# IDX du compteur de granulés
Idx_cpt_gra = '164'
qte_granules_total = 66
poids_sac_granules = 15

# IDX des valeurs de la cuve
Idx_vol_cuve = '177'
Idx_haut_cuve = '176'
config.py

De cette manière, lorsque je suis amené à changer une valeur, je ne suis pas obligé de rechercher les paramètres dans tous les scripts.

Le programme principal

Il est lancé au moyen du Karotz ou à partir du scénario dont le détail est illustré ici

ajout_granulés

Le code n’est pas optimisé, j’en suis conscient mais l’essentiel pour moi c’est que ça fonctionne. Lorsque j’aurais du temps (si ça arrive un jour), je remplacerai urllib par request.

#!/usr/bin/python
# -*-coding:Utf-8 -*
# José - Janvier 2015 - Module de gestion des granulés.
# Permet de relever la valeur du compteur dédié et ajoute la quantité du jour
#
import urllib
import urllib2
import sys
import config # On retrouve le nom du fichier décrit au dessus
import requests

##### Les variables sont stockées dans le fichier config.py
#
# Terme a rechercher
terme='Counter'
#
# Décalage de caractères
offset=5
#
# Longeur de la chaine à garder
lg_chaine_a_garder=2
#
# Initialisation du compteur
val_compteur=''
#
# Debug
debug=0
#
###############  fin des parametres #############################

# l URL Domoticz a interroger pour recuperer les infos est type=devices&rid=XXX
def inter(val_compteur):
        json_url='/json.htm?type=devices&rid='
        requete='http://'+config.domoticz_ip+':'+config.domoticz_port+json_url+config.Idx_cpt_gra #La variable est située dans le fichier config.sonNom

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

        sschaine=ch[debut+offset:debut+offset+lg_chaine_a_garder]

        # Calcul de la quantité en sac et en kg pour le compteur
        # Récupération de la valeur du compteur domoticz
        # Ajoute la quantité de granulés d'un sac
        val_compteur = int(sschaine) + 1

        # Calcul combien il reste de sac pour l'annonce en retirant la valeur du compteur au nb total
        stock = config.qte_granules_total - val_compteur

        # Calcul du poid de la consommation
        poids = val_compteur * config.poids_sac_granules

        # Met les varibales au format texte pour passer dans la requête
        val_compteur = str(val_compteur)
        stock = str(stock)
        poids = str(poids)

        if debug == 1:
                print u'Chiffre de la requête : '+sschaine
                print 'Nombre de sacs consommés : ' +val_compteur
                print 'Nombre de sac restant en stock : '+stock
                print 'Equival conso ' +poids+' kg'

        # Lance la requete de mise à jour du widget compteur
        json_url='/json.htm?type=command%26param=udevice&idx='
        requete='http://'+config.domoticz_ip+':'+config.domoticz_port+json_url+config.Idx_cpt_gra+'&nvalue=0&svalue='+val_compteur
        r=requests.get (requete)

        # Fait bouger les oreilles du Karotz
        the_url= 'http://'+config.karotz_ip+'/cgi-bin/ears_random'
        req = urllib2.Request(the_url)
        handle = urllib2.urlopen(req)

        # Mise en forme du texte en codant les espaces en %20
        texte_lu = config.txt_granules_1+stock+config.txt_granules_2+poids+config.txt_granules_3
        if debug == 1:
                print texte_lu
        result = urllib.quote(texte_lu).encode('utf8')

        # Change la couleur du Karotz en mode normal
        the_url= 'http://'+config.karotz_ip+'/cgi-bin/leds?pulse=1&color=2b00ff&speed=700&color2=def50e'
        req = urllib2.Request(the_url)
        handle = urllib2.urlopen(req)

        # Lance la requête vers le Karotz
        the_url= 'http://'+config.karotz_ip+'/cgi-bin/tts?voice='+config.karotz_voip+'&text='+result+'&nocache=0'
        req = urllib2.Request(the_url)
        handle = urllib2.urlopen(req)

        # Envoi d'un sms sur le portable de José
        url = 'https://smsapi.free-mobile.fr/sendmsg?&user='+config.user+'&pass='+config.pas+'&msg='+texte_lu
        req = urllib2.Request(url)

        try:
                reponse = urllib2.urlopen(req)

        except IOError, e:
                if hasattr(e,'code'):
                        if e.code == 400:
                                print 'Un des paramètres obligatoires est manquant.'
                        if e.code == 402:
                                print 'Trop de SMS ont été envoyés en trop peu de temps.'
                        if e.code == 403:
                                print 'Le service n’est pas activé sur l’espace abonné, ou login / clé incorrect.'
                        if e.code == 500:
                                print 'Erreur côté serveur. Veuillez réessayez ultérieurement.'

        if debug == 1:
                print 'Le SMS a été envoyé sur votre mobile.'

#### MAIN ####
# lance la requete json
inter(val_compteur)

 L’avenir…

Après un échange par mail avec un amateur éclairé, je pense mettre en œuvre l’ajout de sac lors de la réception d’une commande. Ceci ne devrait pas être trop difficile à faire.

Les conseils du jour !

– Le prix des granulés est moins élevé en été et plus les acheteurs sont nombreux moins c’est cher auvergne!

– Faites vos sauvegardes

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

Sauvegarde de sa carte SD vers freebox v6

Bonjour visiteur de passage, je sais je t’ai manqué…

Oui je sais je ne suis pas très assidu mais c’est pas grave…

Pour ceux qui utilisent un raspberry pi, vous savez à quel point les cycles d’écritures sur les carte SD peuvent finir par endommager définitivement, votre serveur domotique perso. Il existe un certain nombre d’articles sur le sujet qui vous démonte la possibilité de faire tourner votre système sur un disque externe tout en concevant une carte SD pour le boot. Mais si tout comme moi, vous n’en faites qu’a votre tête, une sauvegarde complète de votre carte SD n’est pas du luxe.

L’article d’aujourd’hui porte sur la sauvegarde complète de votre carte SD sur une freebox (V6) parce que je n’ai que ça sous la main et que ça marche bien avec l’envoi d’un sms avant et après la copie grâce au service d’envoi de sms de free mobile. Oui je sais si t’a free t’as tout compris).

Bref, allons à l’essentiel:

Les pré-requis:

– une freebox V6 mais avec un peu d’huile de coude le script doit pouvoir s’adapter.

– une installation (domoticz dans mon cas) sur laquelle vous avez passé beaucoup de temps et que la simple sauvegarde des répertoires ne permet pas une remise en service rapide.

– un abonnement free mobile permettant l’envoi de sms gratos sur votre portable préféré.

Fixons une fois pour toute un élément incontournable. La taille du disque de stockage de votre freebox doit être supérieure à la taille de votre carte SD même si le fichier issu de la copie sera compressé.

On commence:

On se connecte comme d’hab au raspberry pi. Puis rendez vous à l’endroit où vous stockez vos scripts. Mon coté psychorigide me fait ranger mes scripts par type (bash, python etc). Dans mon cas, les scripts shell se trouvent ici

/home/pi/domoticz/scripts/shell

J’ai également pour habitude de créer un fichier de configuration qui regroupe les identifiants et mots de passe. Ainsi, le jour où je change, je ne suis pas obligé de me repalucher tout le code.

nano include_passwd

Puis, on ajoute ses petites informations perso: On sauvegarde avec un CTRL x

user='IdentifiantFreeMobile' ; export user
pass='motDePasseFreeMobile' ; export pass

user_box='admin' ; export user_box
pass_box='MotDePasseFreeBox' ; export pass_box

Next Step:

Création du répertoire de montage

sudo mkdir /mnt/freebox

Bien entendu, si vous souhaitez mettre un autre nom, mettez ce qui vous chante mais vous devrez modifier le script qui suit.

Ensuite on tape la commande pour identifier le lecteur correspondant à la carte SD.

sudo fdisk -l

fdisk

On note très clairement le nom de la carte SD ‘mmcblk0’, notez ça quelque part ça va servir.

Dernière chose, la création de son répertoire de stockage sur sa freebox. On se connecte en tapant mafreebox.free.fr dans votre navigateur préféré puis sur Explorateur de fichier (accessible après authentification, le même password que vous avez tapé dans le fichier include_passwd).

Déroulez les emplacements et créer un répertoire Backup_img ou tout autre chose qui vous parle. N’oubliez pas de modifier cela dans le script image.sh décrit plus bas.

Allez zou, on met tout ça en boite dans le script suivant :

nano image.sh

#!/bin/sh
#############
#
# Script de sauvegarde de l'image complète du serveur Domoticz sur une Freebox V6
# Transmission d un SMS avant et après l'opération
#
# José - JANVIER 2015
#
#############

. ./home/pi/domoticz/scripts/shell/include_passwd # comprend les identifiants pour acceder à la freebox et transmission des SMS via FreeMobile

# Formatage de la date debut et de l'heure
DATE_DEBUT=`date +%d-%m-%Y`
H_DEPART=`date +%H:%M:%S`
DEBUT_EN_SEC=$(($(echo $H_DEPART | cut -d':' -f1)*3600+$(echo $H_DEPART | cut -d':' -f2)*60+$(echo $H_DEPART | cut -d':' -f3)))

# Transmission d'un premier sms
message=${DATE_DEBUT}' '$H_DEPART' Début de la sauvegarde image du serveur domoticz.'
curl -s -i -k "https://smsapi.free-mobile.fr/sendmsg?user=$user&pass=$pass&msg=$message"

# Montage de la Freebox
echo "Montage de la Freebox"
/sbin/mount.cifs //mafreebox.freebox.fr/Disque\ dur/ /mnt/freebox/ -o user=$user_box,pass=$pass_box

# Sauvegarde sur la Freebox
echo "Sauvegarde sur la Freebox"
dd if=/dev/mmcblk0 | gzip -9 > /mnt/freebox/Backup_img/srv-domoticz-${DATE_DEBUT}'-'$H_DEPART.img.gz

# Démontage de la Freebox
echo "Démontage de la Freebox"
/bin/umount /mnt/freebox

# Formatage de la date de fin et de l'heure
DATE_FIN=`date +%d-%m-%Y`
H_FIN=`date +%H:%M:%S`

# Découpe pour mise en seconde
FIN_EN_SEC=$(($(echo $H_FIN | cut -d':' -f1)*3600+$(echo $H_FIN | cut -d':' -f2)*60+$(echo $H_FIN | cut -d':' -f3)))

# Calcul de la durée d'execution
DUREE_EN_SEC=$(($FIN_EN_SEC-$DEBUT_EN_SEC))

# Remise en Heure - Minute - Seconde
DUREE_H=$(($DUREE_EN_SEC/3600))
DUREE_M=$((($DUREE_EN_SEC%3600)/60))
DUREE_S=$((($DUREE_EN_SEC%3600)%60))

# Transmission sms avec heure de fin et la durée
message=${DATE_FIN}' '$H_FIN' Fin de la sauvegarde image du serveur domoticz. Durée du traitement '$DUREE_H':'$DUREE_M':'$DUREE_S
curl -s -i -k "https://smsapi.free-mobile.fr/sendmsg?user=$user&pass=$pass&msg=$message"

Pour les adeptes du « copier coller, je lance le script tient c’est curieux ça marche pas » prenez un instant pour modifier les lignes suivantes:

Si vous avez changé le point de montage, changer son nom ici (extrait de la commande) :

/sbin/mount.cifs //mafreebox.freebox.fr/Disque\ dur/ /mnt/freebox/ .../...
ET LA
/bin/umount /mnt/freebox .../...

Pour adapter le nom de votre carte SD, modifier mmcblk0 en rouge par le nom de votre propre carte SD et Backup_img en bleu par le nom de votre répertoire de sauvegarde sur la freebox (extrait de la commande):

dd if=/dev/mmcblk0 | gzip -9 > /mnt/freebox/Backup_img/srv-domoticz .../...

[/pastacode]
Rendons maintenant ce script exploitable grâce à un chmod +x image.sh

Et tentons le premier lancement.

sudo ./image.sh

Là si tout se passe bien, vous devrier recevoir un sms indiquant le début de la sauvegarde et dans quelques temps un second sms indiquant la fin de la sauvegarde avec la durée totale du job. Dans mon cas, raspberry en RJ45 avec une carte SD de 8 Go, il faut compter 2h30 environ.

Petite astuce en cas de plantage, lancez votre script avec la commande suivante :

sudo sh +x image.sh

Vous verrez dans la console le déroulement du script avec entre autres le valeurs des variables…

Il ne reste plus qu’a gérer sa planification (crontab -e) en fonction de la place restante sur votre freebox et votre degré de paranoïa. Mais si vous êtes arrivé à ce stade de la lecture, je suis heureux de voir que je ne suis pas tout seul  🙂

Les sources :

http://blog.nicolargo.com/2013/04/raspberry-pi-faire-un-backup-de-sa-carte-sd.html

La bise

Projet domotique avec domoticz part 1

Salutations visiteur d’un jour,

C’est le premier article d’une série portant sur un projet domotique personnel fait à partir d’un raspberry pi et de quelques composant, beaucoup de patience, de l’huile de coude et des centaines de litres de déca.

Pour mémoire, vous trouverez l’ensemble des composants à avoir ici.

Pour avoir testé pendant quelques mois l’année dernière la Version 1 et après l’avoir passé en production cet hiver, je dois dire que ça fonctionne très bien. La preuve, j’ai démonté notre ancien gestionnaire de chauffage pour le remplacer par un écran LCD qui affiche toutes les 15 min un état du chauffage, des températures et pleins d’autres info.

Au départ, je m’étais mis en tête de détailler mon installation précédente. Mais il faut reconnaitre qu’elle n’était pas très dynamique, l’ajout d’un simple capteur de température rendait la configuration complexe. Quand au packaging DIY ça ressemblait plus à du DBM (Destroy By Myself).

Attention, je parle bien de mes scripts, de mon environnement et non du projet YANA-SERVEUR que j’évoque pendant un temps. J’ai eu le plaisir de tester ce soft et les dernières versions sont toutes aussi prometteuses.

En attendant des photos de la baie informatique et de la box domotique perso, je vous fais un petit topo sur….

domoticz-570x300Et oui j’essaie actuellement domoticz. Vous avez peut être eu l’occasion de découvrir ce projet en scrutant le net à la recherche d’une solution domotique attractive, pas cher et dont la communauté et dynamique.

En cherchant bien sur ce blog, j’ai fait un petit topo sur le site français le plus précis sur le sujet à savoir easydomoticz.

Par quoi je commence ?
  • Téléchargez la dernière image de domoticz disponible sur le site ici,
  • L’installation de l’image se fait de manière classique,
  • A la mise sous tension, faites comme d’habitude le rasp-config qui va bien,

Au reboot, rendez vous sur l’adresse ip de votre serveur:8080. Si éventuellement la page ne s’affichait pas vérifiez que le service est bien actif sur le raspberry. A défaut :

sudo service domoticz start

domo anglais

Menu de la page de garde en anglais pour commencer

Pour modifier les premiers paramètres, tels que la langue et la localisation etc, rendez vous sur Setup puis modifier les paramètres suivants:

  • Langage: Français
  • Localisation à valider impérativement (pour la météo): cliquez sur le lien pour rechercher votre ville.
  • Save à gauche pour commencer.

Je vous laisse découvrir toutes les autres options qui sont, pour la plus part, relativement simples à comprendre.

setupPour bien prendre en main l’outil, je vous invite à découvrir les blogs suivants:

1/ Déclaration du bus OneWire

Pour mémoire ce bus, collecte les températures de 13 capteurs répartis dans la maison et à l’extérieur. Ils sont alimentés par un 5 volts différents du raspberry pi pour une meilleure stabilité. Pas de souci également pour le 5 volts sur le port GPIO 4 car vu la longueur du câblage, j’ai même diminué la résistance de pull up (faut que je cherche m’en rappelle plus ohms).

Vous z’êtes déjà perdus ? Allez zou, pas de blabla, lisez cet article sur Framboise 314

 Sur domoticz, allez sur « Configuration => Périphériques » comme sur l’image.

perif

Vue de la page de périphériques déclarés

Au bas de la page, cherchez dans le menu déroulant 1-wire (system), donnez un nom à ce slot (le nom importe peu et n’influence pas les capteurs qui en découleront). Cochez bien la case « Activé » et laissez le menu déroulant à « Désactiver ».

Ajouter le capteur et il viendra rejoindre les autres dans la liste.

Si des capteurs sont raccordés sur le bus, ils apparaitront automatiquement dans la liste des dispositifs. Si vous en avez plusieurs, soit vous les raccordez un par un [#meilleureoption] soit vous vous faites [#gros mot] comme moi. Dans la liste, le nom attribué par domoticz se trouve être le numéro de série du capteur 28-00000000, pas très pratique pour les différencier.

Bref, finalement on s’en sort entre la liste des capteurs, les températures qui s’affichent à la hausse a grand coup de sèche cheveux. 🙂

Dans cette fameuse liste, cliquez sur la flèche verte, donnez lui un nom et valider. Ci dessous, vous trouverez un exemple.

eau

Vue du capteur déclaré après son nommage.

Dans le menu température, votre capteur apparait désormais et en cliquant sur log, vous verrez dans quelques temps apparaitre un graphique.

panelchauffeau1

Chauffeeau2

Quand tout est fait ça donne un truc comme ça:

panel2

C’est tout pour l’instant, n’hésitez pas a revenir vous perdre ici de temps en temps.

 Fermer, démonter, rouler !

 

 

Le site du jour : easydomoticz.com

Bonjour curieux de passage,

Si tout comme moi vous essayez de trouver la solution domotique la plus adaptée à vos besoins, vous vous êtes certainement penchés sur domoticz.

domo1

Vue écran interrupteurs

Et tout comme moi également, vous avez cherché des infos (en français) sur le net. Bien que la communauté de développeurs sur ce projet soit très active et réactive, j’ai quand même trouvé un site abordant le sujet en français:

Easydomoticz

J’ai trouvé pas mal de petites infos permettant de mieux comprendre le fonctionnement de l’outil. Il faut dire qu’il est plutôt complet et offre de belles perspectives pour se faire une box domotique pour pas grand chose.

Cerise sur le cageot, vous trouverez également un forum pour poser toutes vos questions.

http://easydomoticz.com/forum/

Bonne visite et longue vie à esaydomoticz

domo2

Vue écran températures

Lorsque j’aurai terminé tous mes tests (si j’arrive à finir un jour), je ferai bien un petit post là dessus.