Category Archives: graphs

array('post','marketing','computer','name_of_the_post_type','name_of_the_post_type'))); */ ?>

Suvi de la consommation d’eau avec des compteurs à impulsions sur un bus 1-wire

Contexte

Si vous avez suivi les posts précédents, vous savez peut-être que j’ai aménagé dans une maison neuve, et la construction a ses avantages, comme le fait de penser à installer des compteurs à impulsion par le sanitaire, puis une prise réseau à proximité par l’electricien, ainsi je me retrouve avec ça :

Compteur à impulsion en attente

Compteur à impulsion en attente

Le but étant de suivre la consomation d’eau chaude et d’eau froide.
Le compteur pour l’eau froide est placé avant la nourrice et après l’alimentation du CESI.
Le compteur pour l’eau chaude est placé à la sortie du CESI.
CQFD : inutile dans mon cas de déduire l’eau froide sur l’eau chaude.

Principe

Je vais utiliser un Raspberry Pi et utilise le bus 1-wire pour le comptage des impulsions.
En 1-wire, j’utilise l’interface DS1490 (USB/1-wire) que j’ai acqueri lors des mes découvertes du 1-wire ; car sauf erreur ma part, l’utilisation du 1-wire par les pins du Raspberry Pi ne permettent pas d’exploitrer un DS2423.
Un DS2423 est un double compteur avec mémoire.
Plus tard, je profiterai d’avoir un bus 1-wire pour mettre des sondes de températures DS18B20 à coller aux tuyaux du chauffage qui passent à coté.

Le raspberry est alimenté par le réseau, de plus, ayant besoin d’une alimentation 5 volts pour les composants 1-wire, je ne la prends pas du USB, mais du PoE passif grâce à un simple splitter.

Un schéma de principe :

compteur-impulsion-raspberry-principe

Schéma de principe

 

Dans l’ordre :

  • Les compteurs d’eau génère une impulsion à chaque littre qui passe.
  • Le DS2423 compte chaque impulsion de chaque compteur.
  • Le raspberry consulte le compteur du DS2423.
  • Le raspberry envoi le chiffre obtenu dans une table MySQL sur un serveur.
  • Une page web traire ces chiffres de la table pour générer des graphiques.
  • Je peux me faire la morale parce que mes douches sont trop longues.

Go ?!

Montage du DS2423 pour compter des impulsions

Pour commencer, le DS2423 n’est plus produit, il est en fin de vie.
On peut encore s’en procurer chez hobby-boards.com à 10.50 $ / pièce, auquel on rajoute 10,55 $ de frais de port ! Ce n’est pas rien !

Voici comment j’utilise le DS2423 :

ds2423 schéma

ds2423 : schéma

Il faut donc fournir un bus 1-wire composé d’un « DATA » et d’une masse. Il faut également fournir une alimentation 5V qui a une masse commune avec le bus 1-wire.
Pour l’alimentation, je vais m’inspirer de mon injecteur 5 Volts → 1Wire, sauf que je vais l’inclure dans un seul et même boitier.

 

Schéma injecteur 1-wire

Schéma injecteur 1-wire

+

ds2423 schéma

ds2423 schéma

=

ds2423 avec alimentation

ds2423 avec alimentation

Je me laisse la possibilité de repiquer le bus 1-wire et une alimentation (à droite du schéma) pour ajouter un autre DS2423 dans le but de compter un 3ième compteur à impulsion, voir un 4ième ou un pluviomètre qui se comporte de la même façon qu’un compteur d’eau à impulsion.

Réalisation et mise en place

Est-ce que la théorie rejoint la pratique ?
Je suis parti sur une « prototype board », des borniers, le tout placé dans une prise RJ45 en saillie.
L’avantage d’une prise RJ45 en saillie, c’est quelle permet de planquer le PCB, le tout se  fixe proprement au mur. De plus, j’y connecte à travers le RJ45, un câble RJ11 du DS9490R.
Place aux photos.

Comme on peut le voir, il y a deux DS2423 sur ce montage, c’est en prévision d’un 3ième compteur à impulsion pour un pluviomètre.
Pour ne pas compliquer la chose, on va faire comme si ce deuxième DS2423 n’existe pas.
Sur la dernière photo, on voit clairement les deux compteurs à impulsion raccordés au montage.
La LED permet de vérifier que le circuit est bien alimenté.
Le 5 Volts, provient de l’USB du Raspberry Pi, mais il est préférable de le sortir d’une alimentation sans rapport aux Raspberry Pi, ce qui a été fait entre temps, j’ai utilisé un splitter DC 3,5mm pour alimenter le montage ; le 5V provient du PoE passif.

Récupération des valeurs des compteurs

C’est partie pour une installation de Raspbian sur le Raspberry Pi.
Mes quelques commandes de bases sur le Raspberry :

# sudo passwd
# su
# apt-get update
# apt-get dist-upgrade
# apt-get install htop vim screen usbutils

Puis les choses sérieuses commecent, on branche le dongle DS1490 :

# lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 04fa:2490 Dallas Semiconductor DS1490F 2-in-1 Fob, 1-Wire adapter

On installe owserver, owfs-fuse et surtout owhttps qui permettra de visualiser facilement l’état des compteurs le temps de scripter tout ça.

# apt-get install owserver owfs owhttpd

Puis on modifie le fichier /etc/owfs.conf :
On commente la ligne 16 et décommente la ligne 19.

# vi /etc/owfs.conf
# ...and owserver uses the real hardware, by default fake devices
# This part must be changed on real installation
#server: FAKE = DS18S20,DS2405
#
# USB device: DS9490
server: usb = all
#
# Serial port: DS9097
#server: device = /dev/ttyS1
#
# owserver tcp address
#server: server = 192.168.10.1:3131

Puis on redemarre owserver

# /etc/init.d/owserver restart
[ ok ] Restarting 1-Wire TCP Server: owserver.

Direction le navigateur pour consulter owhttp : http://adresseipduraspberry:2121
Owhttp devrait lister une sonde DS2423 commençant par 1D. 

DS2423 sur OWHTTPD

DS2423 sur OWHTTPD

Ohhhh ! counters.A correspond à mon compteur d’eau froide ; counters.B à mon compteur d’eau chaude.
Après un petit test au verre mesureur, 1 litre d’eau = 1 impulsion. Autrement, la valeur d’une impulsion est généralement marquée sur le compteur, ce n’est pas le cas pour ma part.

Bon, c’est en bonne voie, il reste maintenant à scripter tout ça afin d’alimenter une base de données MySQL sur un serveur distant.
A noter qu’on peut également ecrire les relevé des compteurs sur une base MySQL en local sur le Raspberry ; dans mon cas j’utilise un serveur distant pour d’autres applications lié à la domotique et donc je centralise toutes les données sur une même machine.

Pour insérer les valeurs des compteurs, je m’inspire d’un des mes tuto : Insérer les valeurs 1-wire dans une base MySQL.

Coté serveur MySQL (local/distant, à adapter selon votre convenance)

Nécéssite apache2, php5 et mysql-server  : apt-get install apache2 mysql-server php5
Je crée une base et les deux tables, comme dans mon article, à l’exception de la table 1wire_sensor qui est modifiée pour prendre en compteur les compteurs.
Ce qui donne :

# mysql -p
create database 1wire;
use 1wire;
CREATE TABLE IF NOT EXISTS `1wire_sensor` (
`1wire_sensor_id` int(3) NOT NULL AUTO_INCREMENT,
`1wire_sensor_enable` enum('true','false') NOT NULL,
`1wire_sensor_type` enum('temperature','presence','sensed.A','counters.A','counters.B') NOT NULL,
`1wire_sensor_family` tinytext NOT NULL,
`1wire_sensor_idaddress` tinytext NOT NULL,
`1wire_sensor_comment` text NOT NULL,
PRIMARY KEY (`1wire_sensor_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `1wire_data` (
`1wire_data_id` int(11) NOT NULL AUTO_INCREMENT,
`1wire_data_sensor_id` int(3) NOT NULL,
`1wire_data_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`1wire_data_value` text NOT NULL,
PRIMARY KEY (`1wire_data_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
GRANT ALL PRIVILEGES ON 1wire.* TO '1wire'@'%' IDENTIFIED BY '1wire';

En détail, j’ai ajouté counters.A et counters.B dans le champs 1wire_sensor_type.
Ceci afin de m’adapter aux DS2423 ; counters.A et counters.B sont les noms exact des champs a récupérer.
Faut penser à permettre à notre serveur MySQL d’autoriser les connexions distantes et commenter la ligne bind-address.

# vi /etc/mysql/my.cnf
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
# bind-address = 127.0.0.1
#
# /etc/init.d/mysql restart

Et voila, la partie serveur se termine là pour l’instant, nous y reviendrons pour créer un graphique avec la consomation d’eau.

Pour résumer :
Host : 192.168.1.100
Database MySQL : 1wire
User MySQL : 1wire
Password MySQL : 1wire

Coté RaspberryPi

Là encore, je m’inspire de mon article de l’époque, cependant mon fichier PHP ne traite que les sondes de témpérature et de présence, quelques adaptations sont nécessaires pour explorer un DS2423 :

# cd /root/
# wget https://www.domolio.fr/wp-content/uploads/2012/05/1-wire-mysql.tgz
# tar zxvf 1-wire-mysql.tgz
# cd 1-wire/

J’apporte de suite les informations nécessaires pour la connexion au serveur :

# vi require/main.inc.php

A noter que je travail dans /root/1-wire .

<?php

// -- BASE --

$DEBUG = true;
$DEBUG_TXCOLOR = "#fff";
$DEBUG_BGCOLOR = "#000";
$PATH = "/root/1-wire";

// --

define("DEBUG", $DEBUG);
define("DEBUG_TXCOLOR", $DEBUG_TXCOLOR);
define("DEBUG_BGCOLOR", $DEBUG_BGCOLOR);
define("PATH", $PATH);

// ----
// -- MYSQL --

// Préfixe de toutes les tables du site
$MYSQLHOST = "192.168.1.100";
$MYSQLLOGIN = "1wire";
$MYSQLPWD = "1wire";
$MYSQLBASE = "1wire";

//--

Ah oui, il faut php et php5-mysql

# apt-get install php5-cli php5-mysql mysql-client

Et je créer mon script qui récupère les valeurs des sondes :

# vi /usr/local/bin/1wire-fetch.php

Puis je copie/colle le script de mon article précédent, modifié pour permettre l’intérogation de sondes DS2423 :

#!/usr/bin/php
<?php
$pathconfig = "/root/1-wire";
require_once($pathconfig."/require/main.inc.php");
require_once(PATH."/require/database.inc.php");
require_once(PATH."/require/function-1wire.inc.php");

// Recup des données des sondes depuis la BDD
$req_sensor = "SELECT * FROM 1wire_sensor WHERE 1wire_sensor_enable IS TRUE";
$qur_sensor = mysql_query($req_sensor);
while($dat_sensor = mysql_fetch_array($qur_sensor)) {
 // Pour chaque sonde on constitue son adresse :
 $onewire_address = $dat_sensor['1wire_sensor_family'].".".$dat_sensor['1wire_sensor_idaddress'];
 // On teste sa présence sur le bus
 if(onewire_presence($onewire_address)) {
 debug("OUI ! ".$onewire_address." est présent sur le bus","cli");
 if ($dat_sensor['1wire_sensor_type'] == "presence") {
 debug("Seul sa presence sur le bus est nécessaire","cli");
 // on ecris dans la BDD qu'il est présent et on s'arrete là
 $value = 1;
 }
 elseif ($dat_sensor['1wire_sensor_type'] == "temperature" || $dat_sensor['1wire_sensor_type'] == "sensed.A" || $dat_sensor['1wire_sensor_type'] == "counters.A" || $dat_sensor['1wire_sensor_type'] == "counters.B" ) {
 // on récupère sa valeur, que ca soit la température ou l'état du PIO (DS2406) ou le compteur (DS2423).
 $value = onewire_read($onewire_address,$dat_sensor['1wire_sensor_type']);
 }
 }
 else {
 // Composant absent du bus
 debug ("NON ! ".$onewire_address." n'est pas présent sur le bus","cli");
 $value = 0;
 }

 // on écris le resultat dans la BDD
 $req_insdata = "INSERT INTO 1wire_data SET
 1wire_data_sensor_id = ".$dat_sensor['1wire_sensor_id'].",
 1wire_data_value = '".$value."'";
 mysql_query($req_insdata) or die ("Erreur à l'insertion des données 1-wire : ".mysql_error());
}
mysql_close();
?>
# chmod +x /usr/local/bin/1wire-fetch.php

Puis on fait un break ! Une petite explication s’impose !
Le script 1wire-fetch.php sera appelé par le cron pour remplir une base de donnée sur un serveur distant.
Ce script fait appel à des fichiers stockés dans /root/1-wire/require/ ; ces fichiers sont des « functions » que j’ai pondu il y a quelque temps en utilisant une libraire fournis par l’équipe qui développe 1wire sur linux (owfs.org).
La libraire maitresse, qui permet d’intéroger des sondes par PHP, s’appel libownet-php et fournis un fichier miraculeux qui se nomme ownet.php.

Pour aller plus loin, consulter mon article : Interroger les sondes 1-wire par un script PHP.

Le fichier ownet.php fourni par le paquet libownet-php est buggé, dans l’état, il ne permet pas d’exploiter les DS2423, de plus, c’est ce même paquet que j’ai intégré dans l’archive que vous avez décompressé tout à l’heure.
Mais c’est pas grave, on va débugger ça ensemble.

Pour commencer, adios le fichier ownet.php de mon archive, on va reprendre la version packagé par Debian.

# apt-get install libownet-php
# cd /root/1-wire/require/
# cp /usr/share/php/OWNet/ownet.php .

Puis deux corrections sont nécessaire :

# vi ownet.php

Ligne 516 :

if (bccmp($ret['data_php'],0,0)==-1){

Devient,

if (bccomp($ret['data_php'],0,0)==-1){

Ligne 484 :

$ret['data']    =substr($data,0,$data_len);     // data_php length is the same as $ret[2]

Devient,

$ret['data']    =trim(substr($data,0,$data_len));     // data_php length is the same as $ret[2]

Le premier bug bccmp/bccomp est assez connu, traine depuis très longtemps.
Le second bug est propre au DS2423, j’ai trouvé un seul appel à l’aide sur internet, datant de mars 2010 :
Cannot acces counters DS2423 with ownet.php
C’est donc bien lié aux espaces qui trainent devant la valeur du compteur, chose corrigé avec la fonction php trim().

Ou plus simplement, télécharger directement ma version du fichier ownet.php corrigée :

# cd /root/1-wire/require/
# wget "https://domolio.fr/wp-content/uploads/2015/01/ownet.php.txt" -O ownet.php

Voila, notre break/débug est terminé, pour résumer step by step :

  1. Le cron lance le script /usr/local/bin/1wire-fetch.php
  2. Ce script utilise les fichiers stocké dans /root/1-wire pour se connecter au serveur MySQL distant et au bus 1-wire
  3. Le script consulte la table MySQL 1wire_sensor pour lister les sondes à intéroger sur le bus
  4. Ce même script consulte chaque sonde en verifiant sa présence sur le bus 1-wire et récupère la valeur souhaitée.
  5. Toujours ce script, ajoute les valeurs récupérées dans la table MySQL 1wire_data du serveur distant.
  6. Le script est terminé, il recommencera dans une heure.
  7. Une page web sur notre serveur distant, intéroge les valeurs dans les différentes tables MySQL pour afficher de beaux graphiques.

Ainsi nous allons maintenant alimenter la table 1wire_sensor avec les sondes à intéroger.
Et comme je suis sûr de moi, je le fais depuis mon client, selon les informations MySQL que je me suis mis de coté :

# mysql -h192.168.1.100 -u1wire -p1wire 1wire
INSERT INTO 1wire_sensor SET 1wire_sensor_enable='true', 1wire_sensor_type='counters.A', 1wire_sensor_family='1D', 1wire_sensor_idaddress='641710000000', 1wire_sensor_comment='eau froide';
INSERT INTO 1wire_sensor SET 1wire_sensor_enable='true', 1wire_sensor_type='counters.B', 1wire_sensor_family='1D', 1wire_sensor_idaddress='641710000000', 1wire_sensor_comment='eau chaude';

Pour rappel :
1wire_sensor_family=’1D’ : 1D correspond à la famille des DS2423.
1wire_sensor_idaddress=’641710000000′ : 641710000000 correspond à l’ID de ce DS2423 tel que owhttp me l’a indiqué tout à l’heure.

Il ne reste plus qu’à tester :

# php /usr/local/bin/1wire-fetch.php
[function] onewire_presence pour : 1D.641710000000
OUI ! 1D.641710000000 est présent sur le bus
[function] onewire_read pour : 1D.641710000000 et le type counters.A
La variable value est vide pour le mode counters.A, on recommence (1 fois est normal)
Valeur brute trouvée :972
[result] Donnée trouvée pour /1D.641710000000/counters.A : 972
[function] onewire_presence pour : 1D.641710000000
OUI ! 1D.641710000000 est présent sur le bus
[function] onewire_read pour : 1D.641710000000 et le type counters.B
La variable value est vide pour le mode counters.B, on recommence (1 fois est normal)
Valeur brute trouvée :638
[result] Donnée trouvée pour /1D.641710000000/counters.B : 638

Oh 🙂
Grâce à la première ligne du script ( #!/usr/bin/php ) on peut même directement lancer 1wire-fetch.php :

# 1wire-fetch.php
[function] onewire_presence pour : 1D.641710000000
OUI ! 1D.641710000000 est présent sur le bus
[function] onewire_read pour : 1D.641710000000 et le type counters.A
La variable value est vide pour le mode counters.A, on recommence (1 fois est normal)
Valeur brute trouvée :975
[result] Donnée trouvée pour /1D.641710000000/counters.A : 975
[function] onewire_presence pour : 1D.641710000000
OUI ! 1D.641710000000 est présent sur le bus
[function] onewire_read pour : 1D.641710000000 et le type counters.B
La variable value est vide pour le mode counters.B, on recommence (1 fois est normal)
Valeur brute trouvée :638
[result] Donnée trouvée pour /1D.641710000000/counters.B : 638

Au passage, une petite chasse d’eau + lavage de main aura utilisé 3 litres.
Coté mysql, je devrais avoir toutes les données :

select * from 1wire_data;
+---------------+----------------------+----------------------+------------------+
| 1wire_data_id | 1wire_data_sensor_id | 1wire_data_timestamp | 1wire_data_value |
+---------------+----------------------+----------------------+------------------+
|             1 |                    1 | 2015-01-13 00:37:06  | 975              |
|             2 |                    2 | 2015-01-13 00:37:06  | 638              |
+---------------+----------------------+----------------------+------------------+
2 rows in set (0.00 sec)

C’est le cas !

Je mets en place le cron pour une execution toutes les heures :

# vi /etc/cron.d/crononewire
# Récup des valuers 1-wire tout les 1h et 5 minutes
5 * * * * root /usr/local/bin/1wire-fetch.php

Donc le script se lancera à 13h05, 14h05, 15h05, etc…

Visualisation des données

Le temps passe, la table MySQL se remplit, place aux graphiques !
J’utilise Highcharts et plus précisement sur Highstock qui a l’avantage d’avoir une échelle du temps.
On part du principe que sur la machine qui herberge la partie web pour les graphiques dispose des outils nécessaire : apache2, php-mysql, php5, etc..
Bien entendu, cette partie peut également se situer sur le raspberry, tout comme les données MySQL.

# cd /var/www
# wget https://www.domolio.fr/wp-content/uploads/2015/10/graph-eau.tar.gz
# tar zxvf graph-eau.tar.gz
# cd eau

Le graphique se scinde en deux parties :
– data.php qui récupère les valeurs dans la base de donnéess et qui met en forme au format json.
– index.php et son répertoire « js » qui traite les données et crée les graphiques.

# vi data.php
<php 
header('Cache-Control: no-cache, must-revalidate');
header('Content-type: text/javascript');

$mysql_host = "127.0.0.1";
$mysql_db = "1wire";
$mysql_user = "1wire";
$mysql_pwd = "1wire";

$id_eau_froide = 1;
$id_eau_chaude = 2;

Mon eau froide correspond à l’id « 1wire_data_sensor_id » n°1 dans la table 1wire_data qui correspond à COUNTERS.A de mon DS2423.
L’eau chaude à l’id n°2 -> COUNTERS.B.

Dans le fichier index.php, une seule modification est importante :

$pointStart = "Date.UTC(2015, 0, 13, 0, 0, 0)"
...
$pointStart =  "Date.UTC(2015, 0, 13)";
...
$pointStart =  "Date.UTC(2015, 0)";

« 2015, 0, 13, 0, 0, 0 » correspond à mon tout premier relevé de compteurs :
Le 13 janvier 2015 à 01h soit 00h GMT.

Ici, HighStock travail en intervalle avec les données json reçues par le fichier data.php
On récupère la valeur des compteurs toutes les heures, donc l’intervalle entre deux points pointInterval pour le format :
– Journalier : 3600000 millisecondes (3600 x 1000).
– Hebdomadaire : 3600 x 1000 x 24 x 7.
– Mensuel : 3600 x 1000 x 24 x 31.

Là est le petit faux dans ce script, tous les mois ne font pas 31 jours…
Ça implique un petit décalage visuel de mois en mois.
A corriger à l’occasion…

Voila le résultat :

consomation eau hebdomadaire

consomation eau hebdomadaire

consomation d'eau heure par heure

consomation d’eau heure par heure

consomation d'eau par mois

consomation d’eau par mois

Demo

Une demo figée au 11/10/2015 ici :

http://www.chocolio.com/demo-eau/

Et voila ! Très content de mes compteurs et de mon suivi !
La prochaine étape pour moi, sera d’ajouter un pluviomètre sur le dernier compteur du DS2423, et cela afin d’actionner ou pas un arrosage automatique.

Posté dans 1-wire, Debian, graphs, php, Raspberry Pi, Web | 6 Commentaires

Monitorer la temperature avec un Raspberry Pi, vite fait bien fait

L’hiver arrive, dans la nouvelle maison je souhaite surveiller la température temporairement pièce par pièce pour mesurer l’impact du chauffage.
Pour cela, je m’aide d’un Raspberry Pi en WIFI et d’une sonde 1-wire DS18B20.

Je ne vais pas réinventer le fil à couper le beurre, le schéma de câblage d’un DS18B20 est le même sur tous les blogs :

DS18B20 sur raspberry pi

DS18B20 sur raspberry pi

 

Ce qui donne une fois soudé :

Magnifique tapis de souris

Magnifique tapis de souris

Vite fait bien fait on a dit

Vite fait bien fait on a dit

Avec des pins !

Avec des pins ! Luxe !

J’utilise une résistance de 4.2kΩ qui fait très bien l’affaire.

Coté Raspberry Pi, après la configuration du WIFI, place à la configuration du 1-wire.

# vi /etc/modules
w1-therm
w1-gpio pullup=1
snd-bcm2835

Pour une action immédiate :

# modprobe w1-therm
# modprobe w1-gpio pullup=1

Puis allons voir ce qu’il se passe  du coté du bus 1-wire :

# cd /sys/bus/w1/devices
# ls -l
total 0
lrwxrwxrwx 1 root root 0 nov. 18 00:05 28-000003977b0a -&gt; ../../../devices/w1_bus_master1/28-000003977b0a
lrwxrwxrwx 1 root root 0 nov. 17 22:45 w1_bus_master1 -&gt; ../../../devices/w1_bus_master1

Ah ! 28 machins, ça me rappelle des souvenirs.

# cd 28-000003977b0a
# cat w1_slave
63 01 4b 46 7f ff 0d 10 15 : crc=15 YES
63 01 4b 46 7f ff 0d 10 15 t=22187

Bon, on devine que 22187 correspond à 22,187°C.
Autrement on peut utiliser cette commande :

# find /sys/bus/w1/devices/ -name "28-*" -exec cat {}/w1_slave \; | grep "t=" | awk -F "t=" '{print $2/1000}'
22.187

Voila voila…

Reste à grapher périodiquement cette valeur.
Vite fait, bien fait, j’aime grapher avec munin et j’ai vite trouvé un script simple et efficace :
https://gist.github.com/kminiatures/4f3…

Ah bah !?! Go !

# apt-get install -y munin-node bc
# cd /etc/munin/plugins/

Personnellement, je souhaite juste ma temperature, donc je supprime tous les plugins et crée le nouveau plugin :

# rm *
# vi 1w-temp

Pour y insérer ceci (selon https://gist.github.com/kminiatures/4f3… )

#!/bin/sh

case $1 in
   config)
        cat <<'EOM'
graph_title Temperature
graph_vlabel Temperature
temperature.label temperature
EOM
        exit 0;;
esac

printf "temperature.value "
TEMP=`cat /sys/bus/w1/devices/*/w1_slave | grep t= | sed s/.*t=//`
echo "scale=2; $TEMP / 1000" | bc

Puis on teste tout de suite notre plugin :

# chmod +x 1w-temp
# munin-run 1w-temp
temperature.value 22.25

Bientôt la fin… J’ajoute un « allow * » au fichier /etc/munin/munin-node.conf
Puis /etc/init.d/munin-node restart

Mettons un serveur munin/apache2 en place :

# apt-get install munin apache2
# vi /etc/apache2/conf.d/munin

Puis remplaçer toutes les occurences de Allow from localhost 127.0.0.0/8 ::1 par Allow from all .
On redémarre apache2 :

# /etc/init.d/apache2 restart

Vous pouvez également modifier le fichier /etc/munin/munin.conf pour modifier le nom de votre serveur.

Evidemment, si vous avez un autre serveur munin (mon cas), inutile d’installer un serveur munin sur votre Raspberry, il vaut mieux décharger cette tâche à une autre machine plus apte à ce genre de service.
Au bout de quelques heures ou quelques jours, vous devriez voir ce genre de graphique :

DS18b20 dans munin

DS18b20 dans munin

DS18b20 zoomé dans munin

DS18b20 zoomé dans munin

Bon, vite fait, maintenant qu’on a un apache2 sur le raspberry, une petite page PHP pour connaitre la température actuelle de la sonde.
On peut aussi lire la valeur « Cur: » sur les graphs munin, mais mes petits yeux veulent quelque chose de plus grand, surtout depuis le téléphone.

# apt-get install php5
# cd /var/www/
# vi index.php
<meta name="viewport" content="width=device-width, user-scalable=no">
<center><span style="font-size:65px;">
<?php
// Fichier à lire
$file = "/sys/bus/w1/devices/28-000003977b0a/w1_slave";

// Lecture ligne par ligne
$lines = file($file);

// Recupere la 2nd ligne
$temp = explode('=', $lines[1]);

// Formatage de la temperature
$temp = number_format($temp[1]/1000,2, '.', '');

// On affiche la temperature
echo $temp;
?>
</center></span>

28-000003977b0a correspond à l’ID de ma sonde DS18B20.

Ce qui donne sur smartphone :

page web DS18b20

page web DS18b20

Voila, un article vite fait bien fait, pour surveiller une température.
Cela va me permettre dans un premier temps de calibrer mon Z41.
Puis ça me permettra d’analyser les variations de température de la maison entre le chauffage au sol, le poêle à pellet, et l’ensoleillement à travers les ouvertures.

Posté dans 1-wire, graphs, php, Raspberry Pi, Web | Tagged , , , , | 19 Commentaires

Téléinfo et emoncms, rapide retour d’expérience

Un petit billet pour dire que j’ai commencer à superviser le compteur électrique EDF (téléinfo) avec emoncms.

J’ai suivi deux articles :

Deux petites difficultés:

  • Je n’avais pas désactivé la console série sur le Raspberry Pi, alors que c’est indiqué dans ici : Teleinfo – Préparation d’une Raspberry Pi.
  • Une fois mes données dans emoncms, je ne sais pas trop quoi en faire, sources, feeds, process, nodes, ça ne m’inspire pas trop pour l’instant, mais je me dépatouille.

Quelques photos de l’installation pour les essais :

Lorsque l’installation sera « validée », le téléinfo empruntera une paire en attente dans le boîtier DTI et le raspberry trouvera sa place dans la baie 19″, la partie photocoupleur sera dans un joli petit boitier.


Je ne connaissais pas du tout emoncms, je me suis laissé guider par les nombreux tuto qui existent.
Comme dit un peu plus haut, ma difficulté est de traiter les données reçues.

Emoncms sources

Sources sur Emoncms

 

Feeds emoncms

Feeds emoncms

 

Emoncms visu

La visu sur Emoncms

Si quelqu’un a des conseils à donner sur la façon de traiter les valeurs du téléinfo, je suis preneur…
Le script présenté par hallard.me a l’avantage de pouvoir alimenter emoncms et une table MySQL, ce qui va me permettre de tester d’autres solutions de graphs en parallèle d’emoncms.

Le script de hallard.me disponible sur github, permet en effet de remplir une table MySQL.
Pour ma part, ça représente une avantage important : ne maitrisant pas emoncms, une table MySQL me permet de maintenir une source brutte des données du téléinfo.

La table est constituée ainsi (CTRL+C / CTRL+V de hallard.de) :

CREATE TABLE IF NOT EXISTS `DbiTeleinfo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `DATE` datetime DEFAULT NULL,
  `ADCO` varchar(12) DEFAULT NULL,
  `OPTARIF` varchar(4) DEFAULT NULL,
  `ISOUSC` decimal(2,0) DEFAULT NULL,
  `BASE` decimal(9,0) DEFAULT NULL,
  `HCHC` decimal(9,0) DEFAULT NULL,
  `HCHP` decimal(9,0) DEFAULT NULL,
  `BBRHCJB` decimal(9,0) DEFAULT NULL,
  `BBRHPJB` decimal(9,0) DEFAULT NULL,
  `BBRHCJW` decimal(9,0) DEFAULT NULL,
  `BBRHPJW` decimal(9,0) DEFAULT NULL,
  `BBRHCJR` decimal(9,0) DEFAULT NULL,
  `BBRHPJR` decimal(9,0) DEFAULT NULL,
  `DEMAIN` varchar(4) DEFAULT NULL,
  `EJPHN` decimal(9,0) DEFAULT NULL,
  `EJPHPM` decimal(9,0) DEFAULT NULL,
  `PEJP` varchar(2) DEFAULT NULL,
  `PTEC` varchar(4) DEFAULT NULL,
  `IINST1` decimal(3,0) DEFAULT NULL,
  `IINST2` decimal(3,0) DEFAULT NULL,
  `IINST3` decimal(3,0) DEFAULT NULL,
  `IMAX1` decimal(3,0) DEFAULT NULL,
  `IMAX2` decimal(3,0) DEFAULT NULL,
  `IMAX3` decimal(3,0) DEFAULT NULL,
  `HHPHC` varchar(1) DEFAULT NULL,
  `PMAX` decimal(5,0) DEFAULT NULL,
  `PAPP` decimal(5,0) DEFAULT NULL,
  `ADPS` decimal(3,0) DEFAULT NULL,
  `MOTDETAT` varchar(6) DEFAULT NULL,
  `TENSION` decimal(3,0) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `SEARCH_INDEX` (`ADCO`,`DATE`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Idéale pour le script suivant :

https://github.com/BmdOnline/Teleinfo

Voici les données à modifier du fichier structure.date.php afin de correspond aux données soumises par le script de hallard.me :

    // Adapter les valeurs du tableau si le nom du champ est différent
    "table" => array (
        "DATE"     => "DATE",      // => généralement, vaut soit "DATE", soit "TIMESTAMP"
        "OPTARIF"  => "OPTARIF",   // option tarifaire souscrite
        "ISOUSC"   => "ISOUSC",    // intensité souscrite
        "BASE"     => "BASE",      // BASE
        "HP"       => "HCHP",      // HCHP
        "HC"       => "HCHC",      // HCHC
        "HPJB"     => "BBRHPJB",   // BBRHPJB
        "HPJW"     => "BBRHPJW",   // BBRHPJW
        "HPJR"     => "BBRHPJR",   // BBRHPJR
        "HCJB"     => "BBRHCJB",   // BBRHCJB
        "HCJW"     => "BBRHCJW",   // BBRHCJW
        "HCJR"     => "BBRHCJR",   // BBRHCJR
        "HN"       => "EJPHN",     // EJPN
        "HPM"      => "EJPHPM",    // EJPHPM
        "PTEC"     => "PTEC",      // période tarifaire en cours
        "DEMAIN"   => "DEMAIN",    // prévision du lendemain (formule Tempo)
        "IINST1"   => "IINST1",    // => généralement, vaut soit "IINST1" soit "INST1"
        "PAPP"     => "PAPP"       // puissance apparente
    )

Et voilà, j’ai certe deux outils pour presque la même chose :
EmonCMS, très complet et difficile à maitriser à mon gout, il me faudra du temps pour avoir un monitoring au top.
Teleinfo, simple, très facile à mettre en place, fait le boulot.

 

Teleinfo instantanne

Teleinfo instantanné

Teleinfo sur 24h

Teleinfo sur 24h

Teleinfo historique

Teleinfo historique


Coté tableau électrique, j’ai validé ma période de test et ai sorti le SFH620 de sa platine de tests :

Petite astuce, j’ai collé l’ensemble photocoupleur, bornier, résistance, au boitier du Raspberry en tailladant le plastique pour la colle prenne.

 

Posté dans emoncms, graphs, teleinfo, Web | 6 Commentaires

Insérer les valeurs 1-wire dans une base MySQL

J’ai déjà abordé la récupération des températures dans un graphique munin.
J’ai également abordé la récupération de ces mêmes valeurs en PHP.

Et maintenant, place à la récupération des valeurs pour l’insertion dans une base de données MySQL.
Le but étant de passer par le cron, d’avoir une table avec les sondes, une table avec les valeurs.

J’ai réalisé ce premier ensemble de scripts regroupant pas mal de require, c’est plus difficile à partager pour la compréhension et les explications mais j’espère que ce script restera sous cette forme pour mon usine à gaz définitive.

Structure de la base

Une première table avec les sondes, voici son squelette :

CREATE TABLE IF NOT EXISTS `1wire_sensor` (
  `1wire_sensor_id` int(3) NOT NULL AUTO_INCREMENT,
  `1wire_sensor_enable` enum('true','false') NOT NULL,
  `1wire_sensor_type` enum('temperature','presence','sensed.A') NOT NULL,
  `1wire_sensor_family` tinytext NOT NULL,
  `1wire_sensor_idaddress` tinytext NOT NULL,
  `1wire_sensor_comment` text NOT NULL,
  PRIMARY KEY (`1wire_sensor_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Une seconde table avec les valeurs, son squelette :

CREATE TABLE IF NOT EXISTS `1wire_data` (
  `1wire_data_id` int(11) NOT NULL AUTO_INCREMENT,
  `1wire_data_sensor_id` int(3) NOT NULL,
  `1wire_data_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `1wire_data_value` text NOT NULL,
  PRIMARY KEY (`1wire_data_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Le script automatique

Comme expliqué plus haut, difficile de partager un script complexe pour un besoin simple.
Je fais un « require » pour appeler un fichier de config, un autre pour la connexion MySQL, un dernier pour mes fonctions 1-wire.

Ce qui donne cet ensemble :

<?php
$pathconfig = "/var/www/domy";
require_once($pathconfig."/require/main.inc.php");
require_once(PATH."/require/database.inc.php");
require_once(PATH."/require/function-1wire.inc.php");

// Recup des données des sondes depuis la BDD
$req_sensor = "SELECT * FROM 1wire_sensor WHERE 1wire_sensor_enable IS TRUE";
$qur_sensor = mysql_query($req_sensor);
while($dat_sensor = mysql_fetch_array($qur_sensor)) {
 // Pour chaque sonde on constitue son adresse :
 $onewire_address = $dat_sensor['1wire_sensor_family'].".".$dat_sensor['1wire_sensor_idaddress'];
 // On teste sa présence sur le bus
 if(onewire_presence($onewire_address)) {
 debug("OUI ! ".$onewire_address." est présent sur le bus","cli");
 if ($dat_sensor['1wire_sensor_type'] == "presence") {
 debug("Seul sa presence sur le bus est nécessaire","cli");
 // on ecris dans la BDD qu'il est présent et on s'arrete là
 $value = 1;
 }
 elseif ($dat_sensor['1wire_sensor_type'] == "temperature" || $dat_sensor['1wire_sensor_type'] == "sensed.A") {
 // on récupère sa valeur, que ca soit la température ou l'état du PIO (DS2406)
 $value = onewire_read($onewire_address,$dat_sensor['1wire_sensor_type']);
 }
 }
 else {
 // Composant absent du bus
 debug ("NON ! ".$onewire_address." n'est pas présent sur le bus","cli");
 $value = 0;
 }

 // on écris le resultat dans la BDD
 $req_insdata = "INSERT INTO 1wire_data SET
 1wire_data_sensor_id = ".$dat_sensor['1wire_sensor_id'].",
 1wire_data_value = '".$value."'";
 mysql_query($req_insdata) or die ("Erreur à l'insertion des données 1-wire : ".mysql_error());
}

?>

J’espère que le principe de ce script php reste compréhensible avec les commentaires.

L’ensemble des fichiers sont disponible à la fin de l’article.

Le contenu de la base

Une fois la structure de la base établie ainsi que le script chargé de consulter les élements 1-wire, il reste à saisir les informations liés aux éléments 1-wire.
Pour cela, en plus d’avoir identifiant chaque sonde au moment de son câblage, je me sert de owhttpd pour récupérer l’ID  des sondes. ( http://ipduserveur:2121/ )

Fenêtre fermée, DS2401 présent dans owhttp

Fenêtre fermée, DS2401 présent dans owhttp

J’ai descidé de spliter en deux l’ID des sondes 1-wire.
Par exemple, pour 28.7B2DB5030000 :
– Famille : 28.
– ID : 7B2DB5030000.

Et j’utilise phpmyadmin pour inserer la 1re sonde de température ( 28.7B2DB5030000 ) afin d’obtenir ceci :

Sonde 1-wire dans la base MySQL via phpmyadmin

Sonde 1-wire dans la base MySQL via phpmyadmin

Ainsi de suite pour chaque sonde désirée, 1wire_sensor_id étant la clée primaire en AUTO_INCREMENT.

A terme, le but étant de créer une interface pour gérer l’ajout, l’édition et la supression de sonde plus facilement via une page développée dans ce sens.
Idem pour chaque famille de sonde : température / présence / PIO.

Execution

On peut faire un simple test :

# cd /var/www/1-wire/cron
# php fetch-1wire.php

Vous devriez obtenir les valeurs de température.
Si vous obtenez le message :

PHP Notice: Can’t create socket [ow://127.0.0.1:4304], errno: 111, error: Connection refused in /var/www/1-wire/require/ownet.php on line 205
PHP Notice: Can’t connect get#1 in /var/www/1-wire/require/ownet.php on line 388

Modifiez le /etc/owfs.conf pour remplacer :
server: port = localhost:4304
Par :
server: port = 4304

Redemarrez owserver et refaite le test.

Si tout est ok, l’execution se fait via le cron, tout simplement :

# vi /etc/cron.d/cron1wire
*/5 *   * * *   root    /usr/bin/php -q /var/www/1-wire/cron/fetch-1wire.php

Au bout de quelques heures :

Résultat  de l'insertion des températures 1-wire dans une base MySQL

Résultat de l’insertion des températures 1-wire dans une base MySQL

Télécharger

Télécharger l’archive

A adapter, bidouiller, comprendre, améliorer, etc…

Et bientôt la génération de beaux graphs à partir de ces valeurs.

Posté dans 1-wire, Debian, graphs, php | 5 Commentaires

Générer des graphiques munin grâce aux sondes 1-wire

Grapher grapher grapher et grapher !
Déformation professionnelle ou pas, mais vive les graphs !

Analyser de bons graphiques en dit beaucoup.

  • l’inertie de mon chauffage est-il optimisé ?
  • Pourquoi ce pic de température, comment le lisser ?
  • Pourquoi cette soudaine chute de température ?

Obtenir une vue globale de l’ensemble des températures/hygrométrie, c’est primordial et bien sur, une base fondamentale en domotique.

Dans un premier temps, je souhaite monitorer les sondes de température via munin, plus tard, je doublerais très certainement le schlimblik via une base MySQL pour une meilleure exploitation des données. Il existe déjà des choses farfelues dans ce genre mais j’y reviendrai bien plus tard.

# apt-get install munin munin-node apache2

Je dé-commente et modifie les lignes de munin « /etc/munin/munin.conf » pour le faire fonctionner en tant que « serveur » comme je le souhaite, en rapport avec apache2.

dbdir /var/lib/munin
htmldir /var/www
logdir /var/log/munin
rundir /var/run/munin
#
# Where to look for the HTML templates
tmpldir /etc/munin/templates

J’utilise un script pompé et légèrement modifié de chez Yoann QUERET (qui au passage fait du super taff dans le domaine Asterisk & FreePBX). Merci à lui.

Le fichier du script se situe : /usr/share/munin/plugins/owfstemp

#!/bin/bash
DEVICE=`basename $0| cut -d "_" -f2`
ALIAS=`basename $0| cut -d "_" -f3`

if [ "$1" = "autoconf" ]; then
 echo yes
 exit 0
fi
if [ "$1" = "config" ]; then
 echo "graph_title Temperature $ALIAS"
 echo "graph_info Temperature pour la sonde $DEVICE"
 echo 'graph_args --base 1000 -l 0'
 echo 'graph_vlabel Celsius'
 echo 'graph_scale no'
 echo 'graph_category Temperature'
 echo "$ALIAS.label $ALIAS"
 exit 0
fi
# Pour une utilisation owserver avec owfs
#FS="/mnt/1wire"
#cd $FS/$DEVICE/
#echo "$ALIAS.label $ALIAS"
#echo -n "$ALIAS.value "
#sed -e 's/ //g'#echo

# Pour une utilisation owserver avec ow-shell et owread
TEMP=`owread -s localhost:4304 /$DEVICE/temperature`
echo -n "$ALIAS.value "
echo $TEMP

A noter qu’il est possible d’utiliser owread ou faire un cat/sed du fichier de température de la sonde, il ne me semble pas qu’il y’ait une différence ou une préférence dans l’utilisation.

On veille à rendre le fichier exécutable.

# chmod +x /usr/share/munin/plugins/owfstemp

Et on crée nos plugins munin :

# ln -s /usr/share/munin/plugins/owfstemp /etc/munin/plugins/owfstemp_28.EA54B5030000_Exterieur
# ln -s /usr/share/munin/plugins/owfstemp /etc/munin/plugins/owfstemp_28.7B2DB5030000_Chambre

Bien sûr, les ID changent selon chaque sonde, EA54B5030000 et 7B2DB5030000 me sont indiqués par owhttp http://domy:2121 par exemple.
Un petit essai :

# munin-run owfstemp_28.7B2DB5030000_Chambre
Chambre.value 21.5
munin-run owfstemp_28.EA54B5030000_Exterieur
Exterieur.value 21.125

Restart de munin-node pour la prise en compte de ces 2 plugins.

# /etc/init.d/munin-node restart

Et au bout d’une demi journée :

Graphique extérieur avec munin et une sonde DS18B20

Graphique extérieur avec munin et une sonde DS18B20

Graphique intérieur avec munin et une sonde DS18B20

Graphique intérieur avec munin et une sonde DS18B20

C’est un bon début, une base pour la supervision des températures sur le long terme, il faudra cependant très certainement repenser la récupérations des valeurs vers une base MySQL pour traiter les valeurs à court terme ; mais l’un n’empêche pas l’autre.

Posté dans 1-wire, Debian, graphs | 7 Commentaires