envoyer des commandes X10 avec un RFLINK

  • RFLINK 433mhz
  • X10 RF recepteur comme le CM15

le RFLINK (15€ a fabriquer) est la version opensource du RFXCOM (110€)

c’est une passerelle Radio multi fréquences qui permet de rendre communiquante n’importe quelle box domotique comme Jeedom ou Domoticz. RFLINK est un logiciel qui tourne sur un arduino Mega

RFLINK site officiel

tutoriel en français

le CM15 X10 est une centrale de commande , il a 2 fonctions :

  • autonome : vous le programmez avec le logiciel activehome et ensuite il s’occupe d’envoyer les commandes en courant porteur et/ou Radio suivant les recepteurs
  • passerelle : il reçoit des commandes radio provenant d’une telecommande et les transforme en courant porteur pour commander les appareils

aujourd’hui en 2019 cette technologie est en voie de disparition mais si vous en êtes équipé il est possible de lui redonner une seconde jeunesse en la pilotant avec une box domotique moderne

pour tester le dialogue :

si vous possedez une radiocommande x10 , vous allez recevoir ce type de commande dans le logiciel RFlink loader

20;66;X10;ID=46;SWITCH=8;CMD=ON;
20;67;X10;ID=46;SWITCH=8;CMD=OFF;

il est donc facile de trouver quelle commande il faut envoyer

pour envoyer une commande avec RFLINK , il suffit de taper ceci dans la case  » command to send » de RFlink loader

10;X10;00046;8;ON;
10 = émission
X10 = protocol
00046 = house code 
8 = numéro de l'appareil a commander 
ON ou OFF = la commande

dans le même temps , dans le logiciel  activehome / tools / activity monitor, vous allez voir apparaitre la commande reçu de manière un peu plus claire

RECEIVE RF F8

et la on comprends que si le numéro de l’appareil reste identique , le house code , lui à une correspondance différente . il faudra donc tatonner jusqu’a trouver le bon .

bon en fait c’est pas bien compliqué

00041 = A
00042 = B
00043 = C
00044 = D
00045 = E
00046 = F 
...

Synology : PHP en ligne de commande

Au moment de la sortie de cet article nous sommes en DSM 6 , il y a plusieurs versions de php qui cohabite : vous pouvez  installer la 5.6 (ou la 7) par l’intermédiaire du gestionnaire de paquet, puis dans l’interface webstation du DSM seule les versions que vous avez installées (5.6 ou 7) apparaissent , du coup pas de soucis.

par contre quand on veut utiliser la ligne de commande ( comme par exemple pour lancer un script php via la crontab(ou planificateurs de tache) , on se rend compte qu’une ancienne version reste accessible et vient nous pourrir la vie.

la commande normale pour lancer un script php est :

php -f  /volume1/test/monscript.php

mais la ça pointe sur la vieille version , pour lancer la nouvelle il faut faire :

php56 -f  /volume1/test/monscript.php


Autre problème : si vous voulez utiliser une extension php , il faut savoir que l’installation du serveur php web (PHP-CGI) du webstation est différente de l’installation de php en ligne de commande (PHP-CLI) , du coup les extension activées dans webstation ne le sont pas en ligne de commande.

de quoi se creuser la tête un bout de temps.

par exemple si vous utilisez l’extension mysqli dans votre site web sur le webstation  ,et bien en ligne de commande ca ne marchera pas . vous aurez une erreur du style

Fatal error: Call to undefined function mysqli_connect() 

il va donc falloir activer les extensions en ligne de commande :

recherchez  le php.ini :

php56 --ini

Configuration File (php.ini) Path: /usr/local/etc/php56
Loaded Configuration File: /usr/local/etc/php56/php.ini
Scan for additional .ini files in: /usr/local/etc/php56/conf.d
Additional .ini files parsed: /usr/local/etc/php56/conf.d/webstation-extensions.ini

copier le fichier /usr/local/etc/php56/php.ini dans le répertoire de votre script puis modifier le et ajoutez la ligne suivante dans la rubrique [PHP]

extension = mysqli.so

ensuite utilisez ce nouveau php.ini  dans votre ligne de commande :

php56 -c  /volume1/test/php.ini  -f  /volume1/test/monscript.php

une autre méthode est d’éditer directement le fichier /usr/local/etc/php56/php.ini , par contre je ne sais pas si ça résiste a une mise a jour du DSM.

Lire les données d’une chaudière Hargassner par telnet en python 2.7

Les chaudières Hargassner équipées du touchtronic (de séries depuis 2015, en options avant)  émettent leurs données sur un port telnet, celles avec l’ancienne interface émettent sur un port série.

Je vous présente ici mon projet qui permet d’écouter une chaudière Hargassner  sur son port telnet.

un script python tourne en permanence sur mon raspberry , il récupère les données et les écrits dans une base MariaDB sur mon NAS Synology , ensuite j’affiche les courbes avec un site web en php + Highchart

le projet python se trouve sur github https://github.com/Jahislove/hargassner-python

la partie web ici https://github.com/Jahislove/Hargassner

 

harg3 harg2 harg1

Premier test avec xbee : allumer une LED à distance

Voici venu le moment de tester ses modules xbee avec un premier montage ultra simple. Un interrupteur sur le module 1 et une LED sur le module 2

la résistance sur la LED est une standard de 220 ohm et celle sur l’interrupteur de 10 kohm sert de pull-down pour éviter les valeurs flottantes

xbee-inter-led_bb

coté config des modules , il vous faut installer le logiciel officiel Xctu. Pour la prise en main , je vous laisse regarder sur google , rien de bien sorcier , le plus compliqué reste de comprendre a quoi servent les paramètres mais vous allez voir qu’il n’y a quasiment rien a modifier pour réussir a faire fonctionner vos modules.

Pour commencer je vous conseille de mettre une étiquette numérotée sur vos modules  puis vous branchez le  module 1 (qui sera celui avec l’interrupteur)sur la platine USB explorer , et le cable sur le PC. Une fois le module reconnu voici les paramètres a modifier pour ce premier essai :

un triangle bleu veut dire que la valeur n’est pas celle par défaut

un triangle vert veut dire que la valeur n’a pas encore été enregistré , cliquez sur le crayon a droite pour enregistrer la valeur et le triangle passera au bleu

Capture_2

MY est l’identifiant de ce module et DL l’identifiant du module de destination.ici le module 1 (interrupteur) aura l’adresse 1 et communiquera avec le module 2 (LED) qui aura l’adresse 2

 

 

j’ai choisi le DIO 0 (Digital input/Output) , il correspond a la pin20. le paramètre D0 peut prendre 6 valeurs différentes : dans notre cas on choisi le 3 DI

  • 0-Disabled = désactivé
  • 1-NA            = ??
  • 2-ADC         = entrée/sortie Analogique
  • 3-DI             = Entrée Digitale
  • 4-DO Low   = Sortie Digitale à zero par défaut
  • 5-DO High  = Sortie Digitale à 1 par défaut

le paramètre PR  : on met zero pour désactiver le pull-up interne car on utilise un pull down sur l’interrupteur

le paramètre IR : le module scan les pins toutes les x milliseconde , j’ai choisi 100ms c’est largement suffisant . petite subtilité ici , il ne faut pas oublié que le logiciel se programme en hexadecimal et donc 64 en hexa = 100 en décimal , pour vous aider il y a une petite calculatrice a gauche qui fait la conversion.

voila pour le module 1 ,on s’assure que les triangles soient tous bleu et on peut remplacer le module 1 par le 2 sur la platine . on n’oublie pas ensuite de cliquer sur READ pour rafraichir l’ecran

 

pour l’adressage du module 2 c’est l’inverse de tout a l’heure , le module possède l’adresse 2 (MY)et communiquera avec le 1 (DL)

 

 

Capture_5

on reprends la même pin 0 que tout a l’heure D0 et on la met en sortie digitale low (DO low)

on active le pull-up : PR = 1

 

et pour finir une petite subtilité qu’il ne faut pas oublier : le champ IA . pour le module , ce champ permet d’autoriser ou pas les modules distant a venir modifier l’état de mes pin.

les différentes valeurs sont

  • FF aucune autorisation
  • FFFF autorise tout le monde
  • une adresse : autorise le module correspondant .

dans notre cas je veux autoriser le module 1  , j’aurais donc pu mettre 1 dans la case ,mais bon moi j’ai mis FFFF car j’ai plusieurs modules

Capture_6

 

vous n’avez plus qu’a alimenter le tout en 3.3v et voila c’est magique.

Liste de course xbee

voici la liste du matériel que je vous conseille pour démarrer , en général les platines rouge sont de la marque Sparkfun mais il existe des  équivalent en platine bleu un peu moins cher (ex Hobbytronics )

2 modules xbee  serie 1 (802.15.4) : ref  XB24-AWI-001 ou XB24-API-001 … suivant le modèle d’antenne que vous préferez.

 

1 USB explorer : qui permet de relier le module au port usb d’un PC le temps de le programmer + un cable USB-miniUSB si vous n’en avez pas deja un qui traine.

 

 

2 platines support car les pins du xbee sont au pas de 2mm au lieu de 2.54mm comme pour les breadboards (je vous conseille les rouges , car les bleus sont trop larges et masque une rangée de trou sur les breadboards).

 

 

celles ci étant vierge il faut ajouter les rangées de pin : 4×10 femelles au pas de 2mm et 4×10 males au pas de 2.54mm

 

 

 

il peut être intéressant de remplacer ces platines par  des platines régulées , l’avantage c’est que vous pourrez alimenter ces platines en 5v ou 3.3v au choix , c’est vous qui voyez en fonction de votre type d’alimentation

 

 

Personnellement j’ai tout acheté chez Hobbytronic , c’est le seul site que j’ai trouvé qui a tous les différents composants en stock , ça permet 1 seul frais de port

A cela il faudra ajouter un peu de petit matos electronique pour faire vos essai, mais logiquement vous devriez déjà avoir tout ça en stock : breadboard , cables , interrupteurs , leds , résistances …

Présentation des xbee

Je viens de me lancer dans les liaisons radio pour pouvoir installer des capteurs sans fils .

Pour cela j’ai choisi les modules xbee , l’avantages de ces modules c’est qu’ils sont très répandu et qu’il y a beaucoup de tuto dessus, malheureusement la plupart en anglais. Je vais commencer une série d’article au fur et à mesure de mes découvertes.

Le gros avantage des xbee c’est qu’ils ont 2 modes de fonctionnement, le mode AT et le mode API. en mode API il s’agit de transmettre des frames radio , c’est plus puissant mais aussi plus complexe car il faut interpreter les trames .En mode AT on transmet l’etat des GPIO .

Xbee est une marque qui exploite la norme Zigbee , il existe plein de module différent c’est vraiment le bordel au début pour s’y retrouver surtout qu’un même modèle peut avoir différents noms, je ne vais m’attarder que sur les 2 principaux.

xbee s1

-les xbee 802.15.4 , couramment appelé Serie 1 ou 1mW, sur le module il y a marqué S1 ou rien. Cette série permet la communication point a point (de module a module) ou en point à multipoint (en étoile tous les modules vers un module maitre ) et dans les 2 sens bien sur. La serie 1 est capable de faire du Line passing : les modules peuvent se comporter comme un fils virtuel, vous mettez du 3.3v sur une pin GPIO de l’emetteur et la pin du recepteur fait pareil, et ce, absolument sans aucune ligne de code.

 

 

xbee s2-les xbee Zigbee , couramment appelé Serie 2 ou 2mW, sur le module il y a toujours marqué S2. Cette serie permet en plus la communication en mode maille . attention la serie 2 n’est pas cabable de faire du line passing

 

 

 

les 2 series ne sont pas compatibles, la série 1 elle est la plus facile a maitriser et largement suffisante pour équiper une maison de capteur

dans chaque série on trouve aussi des modèles pro , ils sont exactement identique aux modèles standard mais avec une plus grande portée ainsi qu’une plus grande consommation electrique ( à éviter si vous utilisez une batterie) ils sont aussi beaucoup plus cher , compter 25€ un standard et 45€ un pro

chaque modèle est disponible avec différentes antennes

  • wire : mini antenne
  • PCB: piste de cuivre
  • chip : puce intégré
  • U.fl : petit connecteur pour antenne externe
  • RPSMA :  gros connecteur pour antenne externe

Visualisation des données sur une page web

La série d’articles :

Partie 1 : Installation capteur DS18B20 et lecture en ligne de commande
Partie 2 : Lecture des valeurs avec un script Python basique
Partie 3 : Lecture des valeurs avec un script Python avancé et stockage dans une base MySQL
Partie 4 : Visualisation des données sur une page web

Dans la partie 3 de cet article nous avons vu comment stocker la température dans une base MySQL.

Le moment est venu d’afficher de jolies courbes sur une page web.

matériel necessaire :

  • une base MySQL
  • un serveur web avec php 5.6 (pour php 7 voir le commentaire de Bertrand plus bas)

Je vais vous montrer un exemple simple qui vous mettra le pied a l’étrier , ensuite vous n’aurez plus qu’a laisser parler votre imagination.

Temperature

Pour cela je vais utiliser une librairie de graphique qui s’appelle Highcharts. Elle est très connue, gratuite et il y a des tonnes d’info sur le web. Il n’y a rien a installer , on charge simplement la librairie au début de la page html

J’ai créé un exemple très simple en ne gardant que le strict nécessaire afin de rester le plus clair possible. il suffit de coller ce code dans un fichier index.php. ce code est prévu pour 2 sondes. nous supposerons que la table « PiTemp » contient ces champs « date, sonde1,sonde2 »

  • la partie HEAD permet de charger la librairie Highchart et JQuery
  • la partie php permet d’interroger la base et de préparer les données
  • la partie javascript permet d’afficher le graphique. cette partie n’est pas à écrire vous même , il suffit de copier/coller un exemple depuis le site highcharts.com puis de personnaliser vos options
<!DOCTYPE html>
<html>
<head>
    <title>Mes Temperatures</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="http://code.highcharts.com/highcharts.js"></script>

</head>

<body>

<?php
// ************* preparation de la connexion a MySQL ****************************
    $hostname = "localhost";
    $database = "maBase";
    $username = "monUser";
    $password = "monPassword";

    function connectMaBase($hostname, $database, $username, $password){
        $Conn = mysql_connect ($hostname, $username, $password) or trigger_error(mysql_error(),E_USER_ERROR);
        mysql_select_db($database, $Conn);
    }

// ************* preparation de la requete **************************************
    $query1 = "SELECT date, sonde1,sonde2 FROM PiTemp
                ORDER BY `date` DESC  LIMIT 4000";

// connexion mysql et lancement requete *****************************************
    connectMaBase($hostname, $database, $username, $password); // on ouvre la base
    $req1 = mysql_query($query1) ; // on lance la requete
    mysql_close(); // on ferme la base

// ********** traitement du resultat ********************************************
    while($data = mysql_fetch_assoc($req1)) {
        $dateD = strtotime($data[date]) * 1000; //transforme la date MySQL en timestamp
        $liste1[] = "[$dateD, $data[sonde1]]"; // format data pour highchart [x,y],[x,y].....
        $liste2[] = "[$dateD, $data[sonde2]]";
    }
    $liste1 = join(',', array_reverse($liste1)); // on inverse l'ordre car la requete SQL sort le resultat a l'envers
    $liste2 = join(',', array_reverse($liste2));

?>
<div id="graphique0"></div>
<script type="text/javascript">
//**ceci est du code Highcharts.com*************************************************************************
//** vous pouvez trouver toutes les decriptions des options sur le site officiel****************************
// temperature
$(function() {
    chart1 = new Highcharts.Chart({
        chart: {
            renderTo: 'graphique0',
            type: 'spline',
            zoomType: 'x',
            backgroundColor: null,
        },
        title: {
            text: 'Temperatures',
            style:{
                color: '#4572A7',
            },
        },
        legend: {
            enabled: true,
            backgroundColor: 'white',
            borderRadius: 14,
        },
        xAxis: {
            type: 'datetime',
            dateTimeLabelFormats: {
                month: '%e. %b',
                year: '%b',
            }
         },
        yAxis: [{
            labels: {
                format: '{value} °C',
                style: {
                    color: '#C03000',
                },
            },
            title: {
                text: '',
                style: {
                    color: '#C03000',
                },
            }
        }],
        tooltip: {
            shared: true,
            crosshairs: true,
            borderRadius: 6,
            borderWidth: 3,
            xDateFormat: '%A %e %b  %H:%M:%S',
            valueSuffix: ' °C',
         },
        plotOptions: {
            spline: {
                marker: {
                    enabled: false,
                },
            },
        },

        series: [{
            name: 'sonde1',
            color: 'red',
            zIndex: 1,
            data: [<?php echo $liste1; ?>] // c'est ici qu'on insert les data
        }, {
            name: 'sonde2',
            color: 'blue',
            zIndex: 2,
            data: [<?php echo $liste2; ?>] // c'est ici qu'on insert les data
        }]
    });
});
</script>

</body>
</html>

Transformer un script python en service (daemon)

python-logoVoici la méthode pour lancer un script python en tant que service sur le Raspberry mais c’est valable aussi sur Debian.

 

EDIT : cette astuce n’est valable que sur les versions wheezy de raspbian , elle ne fonctionne plus avec la nouvelle version Jessie

 1 -rendre votre script executable

Pour commencer , assurez vous que votre script soit bien exécutable :

chmod +x monscript.py

testez l’execution de votre script :

./monscript.py

n’utilisez pas la méthode « python monscript.py » car pour la suite du tuto votre script doit être exécutable directement

si votre script ne fonctionne pas , vous avez certainement un problème avec votre shebang ( vous savez la première ligne d’un script )

Normalement sur le Raspberry c’est celle ci :

 #!/usr/bin/python 
2 – créer un lien vers votre script :

un service doit être lancé depuis /usr/bin ou /usr/sbin ,

nous allons donc créer un lien dans un de ces répertoires pointant vers notre script

sudo  ln  -s   /chemin_de_mon_script/monscript.py   /usr/sbin/monscript

notez bien qu’on a enlever l’extension .py

Lire la suite

Stocker la température dans une base MySQL en Python sur le Raspberry – Partie 3

La série d’articles :

  • Partie 1 : Installation capteur DS18B20 et lecture en ligne de commande
  • Partie 2 : Lecture des valeurs avec un script Python basique
  • Partie 3 : Lecture des valeurs avec un script Python avancé et stockage dans une base MySQL
  • Partie 4 : Visualisation des données sur une page web

Le matériel nécessaire :

  • 1 raspberry pi fonctionnel avec Raspbian installé
  • 1 base de données MySQL ou MariaDB en local ou sur un autre serveur

Dans la partie 1 de cet article nous avons vu comment lire un capteur de température avec un raspberry.

L’intérêt de tout cela c’est surtout de pouvoir stocker les températures sur une longue durée et de pouvoir faire des jolis graphiques

Nous allons donc stocker tout ça dans une base MySQL. Je ne vais pas décrire ici l’installation et la configuration de MySQL , pour cela google est votre ami.

Pré-requis :

1 raspberry avec raspbian et python 2.7 (ne fonctionne pas avec python 3)

1 base de données déja fonctionnelle ( MySQL ou MariaDB, les 2 sont completement compatibles)

et bien sur avoir suivi la partie 1

python-logole script qui va faire cela est en Python 2.7 , la base de données est une MySQL/MariaDB stockée sur un NAS Synology.

mais vous pouvez aussi installer MySQL sur le raspberry en local

Je parles de MariaDB car initialement j’avais développé le script pour MySQL mais suite au rachat de MySQL par Oracle , un fork MariaDB entièrement compatible libre a été crée. et sur Mon NAS Synology la migration a été automatique sans me demander mon avis. mais au final je n’ai eu aucune modif a faire sur le script .

 Ne vous laissez pas impressionner par la taille du script , en réalité la partie essentielle fait 1 page , tout le reste c’est du control d’erreur 

ces controles permettent les choses suivantes:

  •  éviter au script de planter si jamais la base est inaccessible 
  •  stocker les données dans une base SQlite en local durant l’indisponibilité de  la base MySQL
  •  restorer les mesures depuis SQlite vers MySQL dés que celle ci est de nouveau dispo.

Nous avons besoin d’ajouter 2 modules :

SQlite3 : installation SQlite3  qui va servir de backup

python-mysqldb : permet à python de dialoguer avec une base MySQL,MariaDB,SQLite

sudo apt-get install python-mysqldb
sudo apt-get install sqlite3

Si vous ne voulez pas vous embeter avec la base SQlite de secours , je vais poster en bas de cet article un script beaucoup plus simple , ne comportant que l’essentiel

Vous pouvez retrouver ce script sur mon github au cas ou vous auriez des problèmes de copier/coller :

https://github.com/Jahislove/Thermo-pi/blob/master/thermo.py

Le script python est commenté pour vous aider a le comprendre

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

#=========================================================================
#              thermo.py
#-------------------------------------------------------------------------
# by JahisLove - 2014, june
# version 0.1 2014-06-16
#-------------------------------------------------------------------------
# ce script lit les temperatures donnees par 3 sondes DS18B20 reliees
# au raspberry pi et les stock dans une base MySQL
#
#
# tested with python 2.7 on Raspberry pi (wheezy) and MariaDB 5.5.34 on NAS Synology DS411J (DSM 5)
#
#-------------------------------------------------------------------------
#
# la base de données doit avoir cette structure:
#CREATE TABLE `PiTemp` (
#  `id` int(11) NOT NULL AUTO_INCREMENT,
#  `date` datetime NOT NULL,
#  `sonde1` decimal(3,1) NOT NULL,
#  `sonde2` decimal(3,1) NOT NULL,
#  `sonde3` decimal(3,1) NOT NULL,
#  PRIMARY KEY (`id`)
#) ENGINE=InnoDB  DEFAULT CHARSET=latin1  ;

#===================================================================

#----------------------------------------------------------#
#             package importation                          #
#----------------------------------------------------------#
import os
import time
import MySQLdb   # MySQLdb must be installed by yourself
import sqlite3

#-----------------------------------------------------------------#
#  constants : use your own values / utilisez vos propres valeurs #
#-----------------------------------------------------------------#
PATH_THERM = "/home/pi/thermo/" #path to this script
DB_SERVER ='xxx.xxx.xxx.xxx'  # MySQL : IP server (localhost if mySQL is on the same machine)
DB_USER='xxxxxxxx'     # MySQL : user
DB_PWD='xxxxxxxx'            # MySQL : password
DB_BASE='xxxxxxxxx'     # MySQL : database name

# vous pouvez ajouter ou retirer des sondes en modifiant les 5 lignes ci dessous
# ainsi que la derniere ligne de ce script : querydb(....
sonde1 = "/sys/bus/w1/devices/w1_bus_master1/28-000005f2424d/w1_slave"
sonde2 = "/sys/bus/w1/devices/w1_bus_master1/28-000005f2764e/w1_slave"
sonde3 = "/sys/bus/w1/devices/w1_bus_master1/28-000005f396a0/w1_slave"
sondes = [sonde1, sonde2, sonde3]
sonde_value = [0, 0, 0]

#----------------------------------------------------------#
#             Variables                                    #
#----------------------------------------------------------#

backup_row = 0
backup_mode = 0

if os.path.isfile(PATH_THERM + 'therm_bck.sqlite3'): # if sqlite exist then resume backup mode
    backup_mode = 1

#----------------------------------------------------------#
#     definition : database query with error handling      #
#----------------------------------------------------------#

def query_db(sql):
    global backup_mode
    global backup_row
    try:
        db = MySQLdb.connect(DB_SERVER, DB_USER, DB_PWD, DB_BASE)
        cursor = db.cursor()
        #---------------------------------------------------------------#
        #     Normal MySQL database INSERT                              #
        #     Fonctionnement normal, insertion dans MySQL               #
        #---------------------------------------------------------------#
        if backup_mode == 0:
            cursor.execute(sql)
            db.commit()
            db.close()
        #---------------------------------------------------------------#
        # RESTORE : when MySQL is available again : restore from SQlite #
        # restauration depuis SQlite vers MySQL apres une indispo de MySQL#
        #---------------------------------------------------------------#
        else:
            logfile = open(PATH_THERM + "thermo.log", "a")
            log = time.strftime('%Y-%m-%d %H:%M:%S') + " INFO : MySQL is OK now : Restore mode started\n"
            logfile.write(log)

            db_bck = sqlite3.connect(PATH_THERM + 'therm_bck.sqlite3')
            db_bck.text_factory = str #tell sqlite to work with str instead of unicode
            cursor_bck = db_bck.cursor()

            cursor_bck.execute("""SELECT 'DEFAULT' as id, date, sonde1, sonde2, sonde3 FROM PiTemp ORDER BY date ASC """)
            result_pitemp = cursor_bck.fetchall ()

            for row in result_pitemp:
                cursor.execute("""INSERT INTO PiTemp VALUES {0}""".format(row))

            db_bck.close()
            log = time.strftime('%Y-%m-%d %H:%M:%S') + " INFO : " + str(backup_row) + " rows restored to MySQL\n"
            logfile.write(log)

            backup_row = 0
            backup_mode = 0
            os.remove(PATH_THERM + 'therm_bck.sqlite3')
            log = time.strftime('%Y-%m-%d %H:%M:%S') + " INFO : restore done, sqlite3 file deleted, returning to normal mode\n"
            logfile.write(log)

            cursor.execute(sql)
            db.commit()
            db.close()
            logfile.close

        #---------------------------------------------------------------#
        #     BACKUP : when MySQL is down => local SQlite INSERT        #
        #  si MySQL est KO , on créé une base SQlite temporaire         #
        #---------------------------------------------------------------#
    except MySQLdb.Error:
        db_bck = sqlite3.connect(PATH_THERM + 'therm_bck.sqlite3')
        cursor_bck = db_bck.cursor()

        if backup_mode == 0: #create table on first run
            logfile = open(PATH_THERM + "thermo.log", "a")
            log = time.strftime('%Y-%m-%d %H:%M:%S') + " WARN : MySQL is down : Backup mode started\n"
            logfile.write(log)

            create_pitemp = """CREATE TABLE IF NOT EXISTS PiTemp (`date` datetime NOT NULL,
              sonde1 decimal(3,1) NOT NULL, sonde2 decimal(3,1) NOT NULL,sonde3 decimal(3,1) NOT NULL
            ) ;"""

            cursor_bck.execute(create_pitemp)

            log = time.strftime('%Y-%m-%d %H:%M:%S') + " WARN : Sqlite created\n"
            logfile.write(log)
            logfile.close

        backup_mode = 1
        cursor_bck.execute(sql)
        backup_row += 1
        db_bck.commit()
        db_bck.close()

#----------------------------------------------------------#

def read_file(sonde):
        """ fonction de lecture d'une sonde """
	try:
		f = open(sonde, 'r')
		lines = f.readlines()
		f.close()
	except:
		time.sleep(60)
		try:
			f = open(sonde, 'r')
			lines = f.readlines()
			f.close()
		except:
			logfile = open(PATH_THERM + "thermo.log", "a")
			log = time.strftime('%Y-%m-%d %H:%M:%S') + " WARN : Sonde not found\n"
			logfile.write(log)
			logfile.close
			exit

	finally:
		return lines

#----------------------------------------------------------#
#             code principal                               #
#----------------------------------------------------------#

# initialize Raspberry GPIO and DS18B20
os.system('sudo /sbin/modprobe w1-gpio')
os.system('sudo /sbin/modprobe w1-therm')
time.sleep(2)

datebuff = time.strftime('%Y-%m-%d %H:%M:%S') #formating date for mySQL

for (i, sonde) in enumerate(sondes):
	lines = read_file(sonde)
	while lines[0].strip()[-3:] != 'YES': # read 3 last char from line 0 and retry if not yes
		time.sleep(0.2)
		lines = read_file(sonde)

	temp_raw = lines[1].split("=")[1]     # when YES then read temp (after =) in second line
	sonde_value[i] = round(int(temp_raw) / 1000.0, 1)

#ecriture dans la base
query_db("""INSERT INTO PiTemp (date, sonde1, sonde2, sonde3) VALUES ('%s','%s','%s','%s')
         """ % (datebuff, sonde_value[0], sonde_value[1], sonde_value[2]))

 

Voila , il ne vous reste plus qu’a lancer ce script a intervalle régulier avec la crontab

Ci dessous , je vous met le meme script simplifié à l’extreme , il se contente de l’essentiel , il est plus facile a comprendre mais il n’y a aucun controle d’erreur

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

#================================================================
#              thermo.py
#----------------------------------------------------------------
# by JahisLove - 2014, june
# version 0.1 2014-06-16
#
# la base de données doit avoir cette structure:
#CREATE TABLE `PiTemp` (
#  `id` int(11) NOT NULL AUTO_INCREMENT,
#  `date` datetime NOT NULL,
#  `sonde1` decimal(3,1) NOT NULL,
#  `sonde2` decimal(3,1) NOT NULL,
#  `sonde3` decimal(3,1) NOT NULL,
#  PRIMARY KEY (`id`)
#) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=28 ;

#================================================================

#----------------------------------------------------------#
#             package importation                          #
#----------------------------------------------------------#
import os
import time
import MySQLdb   # MySQLdb must be installed by yourself

#-----------------------------------------------------------------#
#  constants : use your own values / utilisez vos propres valeurs #
#-----------------------------------------------------------------#
PATH_THERM = "/home/pi/thermo/" #path to this script
DB_SERVER ='xxx.xxx.xxx.xxx'  # MySQL : IP server (localhost if mySQL is on the same machine)
DB_USER='xxxxxxxx'     # MySQL : user
DB_PWD='xxxxxxxx'            # MySQL : password
DB_BASE='xxxxxxxxx'     # MySQL : database name

# vous pouvez ajouter ou retirer des sondes en modifiant les 5 lignes ci dessous
# ainsi que la derniere ligne de ce script : querydb(....
sonde1 = "/sys/bus/w1/devices/w1_bus_master1/28-000005f2424d/w1_slave"
sonde2 = "/sys/bus/w1/devices/w1_bus_master1/28-000005f2764e/w1_slave"
sonde3 = "/sys/bus/w1/devices/w1_bus_master1/28-000005f396a0/w1_slave"
sondes = [sonde1, sonde2, sonde3]
sonde_value = [0, 0, 0]

#----------------------------------------------------------#
#     definition : database query                          #
#----------------------------------------------------------#

def query_db(sql):
    try:
        db = MySQLdb.connect(DB_SERVER, DB_USER, DB_PWD, DB_BASE) #creation du connecteur de la base
        cursor = db.cursor() # creation du curseur
        if backup_mode == 0:
            cursor.execute(sql) #execution de la requete
            db.commit()
            db.close()
#----------------------------------------------------------#
# lit le fichier sonde ,
def read_file(sonde):
    try:
        f = open(sonde, 'r')
        lines = f.readlines()
        f.close()
    except:
        exit

#----------------------------------------------------------#
#             code                                         #
#----------------------------------------------------------#

# initialize Raspberry GPIO and DS18B20
# si vous avez installé ces modules au boot dans /etc/modules
# vous pouvez supprimer les 3 lignes ci dessous
os.system('sudo /sbin/modprobe w1-gpio')
os.system('sudo /sbin/modprobe w1-therm')
time.sleep(2)

datebuff = time.strftime('%Y-%m-%d %H:%M:%S') #formating date for mySQL

for (i, sonde) in enumerate(sondes):
	lines = read_file(sonde)
	while lines[0].strip()[-3:] != 'YES': # read 3 last char from line 0 and retry if not yes
		time.sleep(0.2)
		lines = read_file(sonde)

	temp_raw = lines[1].split("=")[1]     # when YES then read temp (after =) in second line
	sonde_value[i] = round(int(temp_raw) / 1000.0, 1)

query_db("""INSERT INTO PiTemp (date, sonde1, sonde2, sonde3) VALUES ('%s','%s','%s','%s')
         """ % (datebuff, sonde_value[0], sonde_value[1], sonde_value[2])) # on INSERT dans la base

Afficher la température d’une sonde DS18B20 en python sur le Raspberry – Partie 2

La série d’articles :

  • Partie 1 : Installation capteur DS18B20 et lecture en ligne de commande
  • Partie 2 : Lecture des valeurs avec un script Python basique
  • Partie 3 : Lecture des valeurs avec un script Python avancé et stockage dans une base MySQL
  • Partie 4 : Visualisation des données sur une page web

python-logoCe simple script python est prévu pour lire 3 sondes de température DS18B20 et afficher le résultat à l’écran. Vous pouvez facilement ajouter ou retirer une sonde en modifiant les lignes 23 à 28

il sera facile ensuite d’adapter ce script pour créer vos propres programmes Lire la suite