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 | 7 Commentaires

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

Magnifique tapis de souris

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 , , , , | 20 Commentaires

Alimenter des Raspberry Pi par le réseau

Schéma PoE passif pour Raspberry Pi

Une petite astuce permettant d’alimenter plusieurs Raspberry Pi à partir du réseau sans utiliser le PoE tel que la norme le défini.

L’avantage du Raspberry, c’est qu’il se glisse partout dans une maison, il consomme peu (650 mA pour le modele B+) ; l’inconvénient est qu’il ne supporte pas le PoE au sens strict de la norme (IEEE 802.3af), à moins d’y rajouter un module très cher.
Ou bien, en PoE passif, avec un peu de câbles, sans devoir toucher au fer à souder 🙂

Actuellement j’utilise 3 Raspberry Pi :
– Compteur téléinfo et contrôle de l’alarme.
– Compteur à impulsion sur le compteur d’eau et monitoring des températures.
– Dans l’atelier, en tant que poste de travail,  SSH, web, etc…

Voici le nécessaire utilisé :

Transformateur 5 Volts / 3 Ampères :

Récupéré d’un hub USB.
Avec embout en 3,5mm.
Neuf, comptez entre 2 $ et 6 $.

*Pas de photo*

Splitter DC 3,5mm (arraignée) :

1 femelle 3.5mm vers 4 mâles 3,5 mm.
Nombres de sorties à adapter selon le nombre de Raspberry souhaité.
Comptez environ 5,60 $.

Splitter 1 femelle vers 4 mâles

Splitter 1 femelle vers 4 mâles

Injecteur/splitter PoE passif :

Se vend par couple, un mâle 3,5mm et une femelle 3,5mm
Environ 3,16 $ mais moins cher si acheté en lot.

Injecteur passif PoE

Injecteur passif PoE

Adaptateur DC 3,5 mm vers micro USB :

Et la fin ! L’adaptateur DC 3,5mm vers micro USB mâle à brancher dans le Raspberry Pi.
Environ 2 $ / pièce.

Adpatateur 3,5mm femelle vers micro USB

Adpatateur 3,5mm femelle vers micro USB

 


PoE passif pour le Raspberry Pi :

Schéma PoE passif pour Raspberry Pi

Schéma PoE passif pour Raspberry Pi

Coté baie de brassage :

L’adaptateur secteur 5V branché au splitter (arraignée) 1 vers 4 fiches.
A chaque sortie de l’araignée : l’injecteur passif, d’un coté le switch (mâle RJ45 dans le switch), de l’autre le câble RJ45 (femelle RJ45 + cordon de brassage dans le panneau).

Coté Raspberry Pi :

Câble réseau raccordé au splitter PoE passif.
Le câble réseau du splitter dans le Raspberry Pi et la fiche mâle DC raccordé à l’adaptateur DC vers micro USB pour alimenter le Raspbery Pi.

Voila, aussi simple que ça pour une seule alimentation pour plusieurs Raspberry Pi et garder une baie de brassage propre.

Baie de brassage domotique

Baie de brassage, 3 Raspberry alimenté en PoE

Baie de brassage et TGBT

Baie de brassage et TGBT

 

Posté dans Raspberry Pi, Sysadmin | Tagged , , , , , , , , | 7 Commentaires

Z41 Remote disponible pour Android

Ecran BSO sur Z41 Remote Android

Une info peu reprise : l’application Z41 Remote est enfin disponible pour Android.
Depuis bien longtemps les utilisateurs d’iPhone pouvaient contrôler leurs maisons avec leurs téléphones.
C’est maintenant aux utilisateurs Android de pouvoir piloter leurs maisons comme s’ils étaient en face de leur Z41.

Pour rappel, l’application Z41 Remote de Zennio est une application qui permet de dupliquer l’écran du Z41 sur son smartphone.
L’application Android est une Beta.

Elle est grossièrement stable, certaines fonctions sont indisponibles, quelques plantages aléatoires.
Mon Z41 n’est pas encore configuré dans ses plus belles fonctions, mais j’ai d’ors et déjà pu constater que Z41 Remote sur android ne me permet pour l’instant pas :
– D’afficher les graphiques
– De choisir la couleur de mon rail LED RGBW.

Vivement la suite ! (Initialement l’application était prévue pour juillet 2014)

Télécharger Z41 REMOTE pour Android

Page d'accueil Z41 Remote Android

Page d’accueil Z41 Remote

Z41 Remote Android écran principal

Ecran principal Z41

Ecran BSO sur Z41 Remote Android

Ecran BSO

Ecran graphiques Z41 Remote Android

Ecran graphiques Z41 Remote Android

 

Posté dans KNX, Z41 | Tagged , , , | Laisser un commentaire

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 | 8 Commentaires

Virtualiser XPEnology avec Xen pour profiter de Surveillance Station

Dans le choix d’un serveur de vidéo-surveillance (NVR), j’ai longtemps cherché une solution opensource, le premier qui vient, serait ZoneMinder, mais mes tests m’ont permis de le trouver trop lourd, barbant, instable, pas user-friendly.
J’ai continué ma quête du NVR parfait, même dans les freeware et proprio pour un usage habitat. Rien à l’horizon…
Puis je suis tombé sur Surveillance Station disponible sur les NAS Synology, les vidéos Youtube m’ont vendu du rêve (1) (2)

Acheter un NAS Synology pour la vidéo-surveillance, si ça tourne bien, ok…
Mais les NAS « physique » ont des limites de caméras… C’est marqué en petit dans la caractéristique technique de chaque produit de Synology.
Le DS414j par exemple, supporte au maximum 8 caméras.

Documentation technique DS414j

Morceau choisi de la documentation technique DS414j

Je suppose que du nombre de baie découle la puissance de matériel et donc du nombre de caméras possible.
Je compte installer entre 5 et 8 caméras, donc il faut que je compte ~ 300 € TTC sans disque pour acheter le NAS suffisament performant.

XPEnology

Puis j’ai découvert XPEnology, Korben vous fait les présentations.

Etant donné que j’ai déjà un serveur debian pour usage multimédias et domotique, autant virtualiser XPenology sur ce même serveur !

Excusez le manque d’analyse et d’informations de XPenology, DSM, et autre outils relatfis au NAS. J’ai prodé ça le même jour où je l’ai découvert, on peut parler d’un coup de foudre.

Installer Xen sur Debian Wheezy

Les how-to sont nombreux sur la toile, parfois trop complet, alors je vais droit au but :

# apt-get install xen-tools xen-system-amd64 xen-hypervisor-4.1-amd64 bridge-utils

On déplace l’ordre de boot des kernel pour booter sur le kernet Xen.

# mv /etc/grub.d/10_linux /etc/grub.d/50_linux
# update-grub

Humm, avant tout, assurez vous d’avoir un processeur capable de virtualiser :

# egrep 'vmx|svn' /proc/cpuinfo

Si vous avez  au moins une ligne qui ressort avec les flags, c’est que votre CPU supporte la virtualisation.
Cependant, si vous avez pris de l’avance et exécutez cette commande en étant déjà sur un kernel Xen, le résultat attendu ne s’affichera pas.

Après un reboot, vous devriez vous retrouver sur un kernel Xen. Pour s’en assurer, faites appel à l’un de ses services 😉

# xm li
Name ID Mem VCPUs State Time(s)
Domain-0 0 2904 4 r----- 67.2

Point important, c’est bien beau d’avoir un processeur pouvant virtualiser, mais assurez vous que l’option est active dans le BIOS, pour cela executez cette commande :

# cat /sys/hypervisor/properties/capabilities
xen-3.0-x86_64 xen-3.0-x86_32p hvm-3.0-x86_32 hvm-3.0-x86_32p hvm-3.0-x86_64

Si la ligne ne fait pas référence à du HVM malgré que vous possédiez un procésseur avec technologie VT-x/AMD-V (flag vmx ou svn), c’est que l’option VT-x/AMD-V est désactivée dans le BIOS (je me suis fait avoir…).
Nous allons faire du HVM (Hardware Virtual Machine), et non de la paravirtualisation, plus de détails sur wikipedia.

Faire de la virtualisation complète, ça permet de ne pas se préoccuper de l’OS sur lequelle XPenology est ‘tiré’, ça a  l’air d’être du FreeBSD, bref je m’en moque.

Xen est installé, un peu de paramétrage, je vous affiche brut ma config :

# egrep -v '^(#|$)' /etc/xen/xend-config.sxp
(network-script network-bridge)
(vif-script vif-bridge)
(dom0-min-mem 196)
(enable-dom0-ballooning yes)
(total_available_memory 0)
(dom0-cpus 0)
(vnc-listen '0.0.0.0')
(vncpasswd '')
(keymap 'fr')

Le fichier de configuration tel quel me permet de fonctionner en mode bridge, et de la possibilité de me connecter en VNC à la machine virtuelle.
De nombreuses possibilités avec Xen, j’adore cet outil, comme dit au début, je vais droit au but, mais sachez qu’il possible de faire énormement avec Xen.

Viritualisation de XPenology

Voila le vif du sujet !
Du peu que j’ai regardé au sujet de XPenology, c’est qu’il s’installe sur une petite partie d’un disque du NAS, pour ma part, pour plus de souplesse, je préfère dédié un disque au fonctionnement de XPenology. Je commence par lui créer un disque de 8Go, au format fichier:

# dd if=/dev/zero of=/srv/xpenology.img bs=1 count=1 seek=8G

Pourquoi 8Go ? Parce que j’ai lu sur xpenology.com/forum qu’il fallait au minium 5Go. Certains parlent de 100Go.
J’admet ne pas avoir tout suivi sur l’emplacement du system d’XPenoloy, où est-ce qu’il se loge, la place qu’il prend, comment il gère le changement de disque.

Autrement, je dédie un disque physique au XPenology.
Dans mon cas /dev/sdd, un disque de 2To.
Cependant, j’ai constaté que je devais partitionner mon disque pour que DSM puisse créer un volume.
J’ai donc crée une partition primaire de 2To -> /dev/sdd1, non formatée, DSM s’en chargera.

Donc 2 supports :
– 1 disque image pour le système.
– 1 disque (ou partition il faudrait dire) de données pour les enregistrements, etc…

Il faut télécharger et mettre sur le serveur, l’image de boot de XPenology, que l’on trouve ici:
http://www.xpenology.nl/boot-images/
→ Gnoboot-10.5 DSM 5.0-4458 X64
Ou bien :
→ Nanoboot-5.0.3.2 DSM 5.0-45XX X64

Gnoboot :
Il a la réputation d’être stable et performant surtout sous environnement virtualisé.
Aucune mise à jour n’a eu lieu depuis longtemps : Aïe !
Les mises à jour de synology se font avec des pincettes, tant que Gnoboot n’évolue pas, peu de possibilités d’upgrader la version 4558.

Nanoboot :
C’est suivi et recommandé par la communauté.
Normalement performant, mais peu s’améliorer ou se dégrader selon la release utilisée.
Les mises à jour de synology se font généralement sans soucis, attendre quelques jours après une nouvelle release pour voir si un fix/problème fait son apparition.

Je stock l’iso dans /root/

Pour créer une machine virtuelle Xen, il faut crée un fichier .cfg
Ma machine virtuelle s’appelle synocam, mon fichier est donc /etc/xen/synocam.cfg et il contient ceci :

Dans le cas d’utilisation de GnoBoot :

kernel = '/usr/lib/xen-4.1/boot/hvmloader'
builder = 'hvm'
memory = '1024'
device_model='/usr/lib/xen-4.1/bin/qemu-dm'
# Disks
disk = [ 'file:/srv/xpenology.img,hda,w','phy:/dev/sdd1,hdb,w','file:/root/gnoboot_105_xpenology_5.0-4458_bootloader_X64_by_Poechi.iso,hdc:cdrom,r' ]
# Hostname
name = 'synocam'
# Networking
vif = [ 'mac=00:11:11:76:75:74,bridge=eth0' ]
# Behaviour
boot='dc'
# VNC
vnc=1
vncviewer=1
vncpasswd=''
sdl=0
usbdevice='tablet'
# Misc
localtime=1
# On fail
on_poweroff='destroy'
on_reboot='restart'
on_crash='restart'

Dans le cas d’une utilisation de NanoBoot, la configuration du domU change un peu :

kernel = '/usr/lib/xen-4.1/boot/hvmloader'
builder = 'hvm'
memory = '1024'
device_model='/usr/lib/xen-4.1/bin/qemu-dm'
vcpu=2
# Disks
disk = [ 'file:/srv/xpenology.img,hda,w','phy:/dev/sdd1,hdb,w','file:/root/NB_x64_5032_DSM_50-4528_Xpenology_nl.iso,hdc:cdrom,r' ]
# Hostname
name = 'synocam'
# Networking
vif = [ 'model=e1000,bridge=xenbr0,mac=00:11:11:76:75:74']
# Behaviour
boot='dc'
# VNC
vnc=1
vncviewer=1
vncpasswd=''
sdl=0
usbdevice='tablet'
# Misc
acpi = '1'
apic = '1'
localtime=1
viridian=1
xen_platform_pci=1
# On fail
on_poweroff='destroy'
on_reboot='restart'
on_crash='restart'

La conf est sortie d’un tiroir, d’un serveur Xen en prod virtualisant du Windows 2008 R2.
L’adresse MAC est modifiée pour simuler un NAS Synology sur le réseau afin d’être détecté par l’assistant Synology.
Le driver virtuel e1000 est utilisé par nanoboot, car le driver par defaut realtek r8169 n’est pas compilé dans nanoboot.
Elle doit commencer par 00:11:11:    . Le reste est inventé.
file:/srv/xpenology.img,hda,w correspond à mon disque image de 8Go, en tant que disque primaire, accès en écriture.
phy:/dev/sdd1,hdb,w correspond à mon disque/partition de 2To, en tant que disque secondaire, accès en écriture.
file:/root/gnoboot_105_xpenology_5.0-4458_bootloader_X64_by_Poechi.iso,hdc:cdrom,r correspond au bootloader de Xpenology, simulé dans un lecteur CD, accès en lecteur seul.
boot=’dc’ permet à la machine virtuelle de booter sur le CD.
memory = ‘1024’ peut être augmenté.
Le nombre de CPU dédié à cette machine est de 1, le nombre peut être adapté avec l’option vcpus=2 pour 2 CPUs dédiés par exemple.
Pour le disque dédié également, vous aurez la possibilité de jongler entre disques physiques, raid soft, raid hard, LVM, laisser DSM gérer ou ajoutant simplement des disques, ou gérer vous en amont les disques que vous incluez dans la machine virtuelle. Voir même le tromper en montant un partage d’une autre machine. J’apprécie cette souplesse !

Voila pour l’essentiel de la config de la machine virtuelle.

Installation de XPenology

A  ce stade, la configuration de Xen et le fichier de configuration de la machine virtuelle devraient permettre de démarrer celle-ci sans erreur.
Si quelque chose manque, Xen vous le fera très vite savoir, c’est tout bon ou rien. Préparez votre client VNC, ça va aller très vite.

Pour démarrer la VM :

# xm create synocam.cfg

Puis ouvrez vite votre client VNC pour vous connecter au serveur, en indiquant le nom où l’ip du serveur Xen.
Vous devriez voir assez rapidement le menu de selection du bootloader GnoBoot.

Menu grub de Gnoboot

Menu grub de Gnoboot

Sélectionnez la seconde ligne Install/Upgrade.
Laissez booter, souriez, ça avance !

Boot de GnoBoot

Boot de GnoBoot

Lorsque le boot est installé, lancez sur votre PC l’utilitaire Synology Assistant.
Il devrait voir votre faux NAS, faite un clic droit > Installer.
Un wizzard vous guide dans l’installation et vous demande un fichier .pat.
Vous pourrez télécharger le  fichier .pat sur le support de Synology :
http://download.synology.com/download/DSM/5.0/4458/
URL et fichier PAT à adapter selon la version que vous cherchez à installer, en rapport avec GnoBoot.
Dans notre cas DSM 5 version 4458 pour le NAS DS3612xs.

Installation en cours par Synology Assistant

Installation en cours par Synology Assistant

♫ Et ça continue encore et encore, c’est que le début d’accord d’accord  ♫

Installation terminez ! Enjoy !

Installation terminez ! Enjoy !

Connectez-vous dés à présent en HTTP à votre nouveau NAS entièrement virtualisé sous XEN.
DSM vous aura crée un volume sur votre petit disque de 8Go, vous pourrez supprimer ce volume pour n’utiliser que le disque dédié.
Gérez vos volumes, changez votre mot de passe, le nom de machine, installez vos paquets : Surveillance Station.

Capture d'écran de DSM sous Xen

Capture d’écran de DSM sous Xen

Pour terminer

J’utilise le SNMP sur DSM pour les graphs munin, sur DSM : Panneau de configuration > Terminal & SNMP; SNMP v2 avec communauté « public« .
Un petit retour sur notre Debian.
Ajout d’un node munin :

# munin-node-configure --shell -snmp synocam

Executez ce que vous avez envie de grapher.
synocam étant le hostname de mon NAS Synology sur mon réseau, à adapter.

Vous pourrez voir l’utilisation des ressources de votre XEN grâce à la commande xm top.

xm top pour voir l'utilisation des ressources

« xm top » pour voir l’utilisation des ressources

Démarrage automatique de la VM avec le serveur Xen :

# mkdir /etc/xen/auto/
# cd /etc/xen/auto/
# ln -s /etc/xen/synocam.cfg .

Pour éteindre votre NAS :

# xm shutdown synocam

Et voila, une très bonne solution à bon gout pour profiter de Surveillance Station.
Je n’ai pas lancé de benchmark sur le bouzin, mon benchmark va surtout se faire au fur et à mesure des ajouts de caméras.

Posté dans NVR, Sysadmin, Web, Xen | 8 Commentaires

Dans la maison prête à domotiser

Un an, trois mois et trois jours, c’est le temps qui s’est écoulé depuis mon dernier article, c’est aussi le temps pour construire 4 murs et un toit.
Au-delà de l’achat du terrain, de l’élaboration des plans avec un architecte, et de la construction qui a debutée début novembre, un peu de neuf coté domotique.

 Accompagnement avec un intégrateur : Concept ED

Chose que je conseillerai à toutes les personnes qui veulent se lancer dans la domotique : se faire accompagner.
Parce que les conseils avisés d’un professionnel sont primordiaux ; partir en solo pour faire des bourdes, avoir une maison domotisée mais incomplète, illogique, mal pensée ou mal programmée, ça serait bien dommage par rapport au budget électricité qui y est consacré.
Certes, l’accompagnement avec un intégrateur est un coût supplémentaire, mais c’est la clé pour un projet réussi.
Croyant avoir entassé beaucoup d’infos sur la domotique, et aurais pu partir avec mes propres connaissances, l’aide de forums et de très bonnes Mailings, mais je préfèrais m’engager avec un intégrateur pour son oeil professionnel et son expérience.

Dans ce domaine, mon choix s’est orienté vers Concept-ED.

Logo Concept ED

Concept ED – Intégrateur domotique en Alsace

Pour en savoir pour sur la société :

 Le « qui fait quoi ? » de la maison domotique

Je me suis fait un « tableau » pour évaluer les différents besoins du projet.
Par pièce, chaque lumière est commandée par  tels intervenants. Chaque prise, etc…

Morceau choisi du pseudo cahier des charges

Morceau choisi du pseudo cahier des charges

Bien pratique pour synthétiser le projet, estimer les besoins en modules, interrupteurs, boutons poussoirs.
Le tout en rapport avec un plan sur lequel chaque élement est positionné.
Le travail en amont avec un intégrateur et l’expérience de l’électricien ont permis de peaufiner le projet.

Tableau électrique

AvantPendantAprès
Tableau éléctrique avant

Tableau éléctrique avant

Tableau électrique pendant

Tableau électrique pendant

Tableau electrique terminé

Tableau electrique terminé

Quelques 65 gaines ont été placées.
L’ensemble de mes modules KNX Hager achetés sur eBay on pu être utilisé, sans devoir en ajouter, ni en retirer.

Poêle à pellets domotisable ou presque

Notre maison sera chauffée avec un poêle à pellets.
L’un des critères du choix de poêle, est de pouvoir le domotiser.
Dans ce domaine là, la marque Edilkamin sort du lot. Les howto sont facilement trouvable sur le net, ils se domotisent à l’aide d’un ou deux contacts secs sur une connectique type RS232.

Dans notre cas, RT2012 et confort oblige, nous recherchons un poêle répondant à ces critères:

  • « étanche » RT2012.
  • canalisable avec 2 sorties d’air chaud.
  • 9kW.

Rien ne correspond à ces trois critères supplémentaires chez Edilkamin.

Nous nous tournons ainsi vers la marque CMG (Caminetti Montegrappa).
Le poêle en question dispose également d’une prise USB à l’arrière, mais je n’ai encore trouvé personne qui a apporté la réponse sur l’utilisation de cette prise en domotique.

Carte mère poêle CMG

Carte mère poêle CMG

Les différents fabricants sont muets sur les connectiques de leurs poêles, c’est bien dommage pour ceux, comme moi, dont la domotisation du poêle est un critère important…

J’espère apporter des réponses au cours de cette année.

Achat groupé ETS4

J’ai profité en fin d’année 2013 d’un achat groupé du logiciel de programmation ETS4. La commande groupée a été (comme à son habitude) organisée la communauté Allemande http://knx-user-forum.de.
Ce forum a l’avantage d’être autorisé à organiser des commandes groupées pour l’achat du logiciel ETS4.

Plus d’information, sur le thread dédié du forum :
http://knx-user-forum.de/knx-eib-forum/34958-ets4-sammelbestellung.html

Google Traduction… Pour résumer le prix est avantageux :
ETS4 avec licence en fichier coûte normalement 800 € HT.
Avec une TVA de 21% (belge) : 968 € TTC.
Auquel il faut rajouter 15€ HT de frais de dossier, soit 18,15 € TTC.
Donc normalement la licence ETS4 coûte 986,15 € TTC.

Grâce à la commaunté knx-user-forum.de.
Ils permettent d’obenir un « voucher » d’une réduction de 400 € HT.
La licence ETS4 file m’a coutée 623,15 € TTC.
Soit une réduction de 37 % ! Merci à eux !

Ce genre de vente a lieu environ tous les 6 mois, en espérant que l’opération ne soit pas figé dans l’attente d’ETS5.
Lisez bien le sujet sur le forum de la communauté lié à cette commande groupée si ça vous tente.

Ca reste une sacrée somme pour commencer à mettre les pieds dans le KNX, surtout pour un particulier qui n’aura certainement qu’un seul projet à suivre.
On espèrant ne pas regreter cet achat…

Dans le prochain épisode

Maintenant que le terrain de jeu est en place, y’a plus qu’a…
Le programme est bien chargé :
– Programmation propre des fonctions de bases KNX : lumières, volets, chauffage, etc…
– Programmation évoluée du KNX  : fonction « aurevoir », Z41, store/alerte vent, etc…
– Compteur d’eau à impulsion avec Raspberry Pi.
– Monitoring du ballon thermodynamique.
– Doorphone SIP.
– Vidéo-surveillance.
– Domotisation du poêle à granules.

A bientôt !

Posté dans KNX | 50 Commentaires

Une interface web pour contrôler le bus KNX sur Raspberry Pi

Raspberry Pi logo

Raspberry Pi logo

Pour reprendre mes différents articles sur le bus KNX, j’ai décidé de passer mon projet sur Raspberry pour vérifier que mes lignes de commandes sont toujours d’actualitées, effectuer un point sur ce que j’ai fait, pouvoir partager le schmilblick.

En plus d’être à la mode, le Raspberry Pi a un très belle avenir dans la domotique !

Comme ce blog est rédigé au fil de mes découvertes du KNX, j’ai essayé de synthétiser mon article sur la prise de contrôle du bus via jQuery.
A savoir que ce qui suit peut également être refait sur du i386…

Objectif

Re-partir de zéro et d’arriver à une interface web permettant d’allumer/éteindre une lumière et de régler sa luminosité (TXA213).
Pouvoir lire et écrire à tout va sur le bus KNX ; l’état des élèments soit lisible et modifiable, un max de souplesse !

La base

Dans un premier temps, je pars sur une base de Raspbian wheezy (sans démarrage de X11) – de très bon tutoriaux existent sur la toile – puis c’est parti pour l’installation d’eibnetmux sur Raspberry.
Pourquoi eibnetmux et pas eibd ? Parce qu’au fur et à mesure de l’utilisation je trouve personnellement qu’eibnetmux est plus simple d’utilisation, plus complet, mieux fini.

# sudo passwd
# su
# apt-get update
# apt-get dist-upgrade
# apt-get install build-essential

Coté Raspberry Pi, je fais tout en root, ajoutez vos outils préférés, nano, vim, alias, etc…

Coté KNX je dispose simplement d’un module HAGER TXA213 : 3 sorties variables 300W
Deux groupes d’adresses :
0/0/1 : sortie 1 → On/Off + indication d’état
0/0/2 : sortie 1 → Valeur d’éclairement + indicateur valeur d’éclairement.

Note : C’est un exemple de groupe d’adresses, apriori, j’ai lu qu’il est préférable de séparer l’indication d’état de  la commande on/off, sans savoir pour quelle raison.

Ainsi que du classique : une alimentation KNX, un routeur IP/KNX et son alimentation dédiée.

Schéma de base KNX

Schéma de base KNX

Téléchargement et installation de Zlogger

Quelques libraires nécessaires pour l’installation :

# apt-get install libpth20 libpth-dev libpolarssl0 pkg-config pth-dbg

Zlogger 1.5.0 est nécessaire au fonctionnement d’eibnetmux.

# cd /usr/src/
# wget "http://downloads.sourceforge.net/project/zlogger/zlogger/1.5.0/zlogger-1.5.0.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fzlogger%2F&amp;ts=1334692716&amp;use_mirror=freefr" -O zlogger-1.5.0.tar.bz2
# tar xfv zlogger-1.5.0.tar.bz2
# cd zlogger-1.5.0
# ./configure --with-plugins --enable-pth-plugins
# make
# make install
# ldconfig

Télechargement et installation d’eibnetmux

Plus de détails dans l’article dédié à eibnetmux et eibd.
La version d’eibnetmux est la dernière disponible selon le site de son auteur via sourceforge.

Pour utliser eibnetmux avec php, celui-ci est nécessaire*.

# apt-get install php5 php5-dev php-pear

* Merci à jjay pour ces infos en commentaires

Puis on installe eibnetmux

# cd /usr/src/
# wget "http://downloads.sourceforge.net/project/eibnetmux/eibnetmux/2.0.1/eibnetmux-2.0.1.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Feibnetmux%2Ffiles%2Feibnetmux%2F2.0.1%2F&amp;ts=1334739400&amp;use_mirror=netcologne" -O eibnetmux-2.0.1.tar.gz
# tar zxvf eibnetmux-2.0.1.tar.gz
# cd eibnetmux-2.0.1
# ./configure --enable-php
# make
# make install
# ldconfig

On récupère et installe le « Sample client applications » ; ce package contient les fichiers PHP nécessaires pour un lire et écrire sur le bus KNX..

Il contient également les commandes de bases équivalentes à groupread, groupwrite, groupswrite, groupsocketlisten, etc…

# cd /usr/src/
# wget "http://downloads.sourceforge.net/project/eibnetmux/Sample%20client%20applications/1.7.1/eibnetmuxclientsamples-1.7.1.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Feibnetmux%2Ffiles%2FSample%2520client%2520applications%2F1.7.1%2F&amp;ts=1361557458&amp;use_mirror=freefr" -O eibnetmuxclientsamples-1.7.1.tar
# tar xvf eibnetmuxclientsamples-1.7.1.tar
# cd eibnetmuxclientsamples-1.7.1

Pause !
Une grosse modification apportée à un fichier, il s’agit du fichier eibtrace/eibtrace.c :
J’ai modifié le fichier pour retourner à une syntaxe plus simple à traiter :

eibtrace.c

J’ai également ajouté un « fflush(stdout);« , sans cet ajout, eibtrace ne parvient pas à rediriger stdout vers un fichier. Et comme le C++ et moi, ça fait deux, je me contente de cette rustine…

Et on compile les scripts d’exemples d’eibnetmux.

# ./configure
# make
# make install

Le petit souci étant que je n’ai pas trouvé l’astuce pour compiler directement dans /usr/local/bin ou équivalent.
Alors en attendant …

# cp eibcommand/eibcommand /usr/local/bin/
# cp eibmultiread/eibmultiread /usr/local/bin/
# cp eibread/eibread /usr/local/bin/
# cp eibstatus/eibstatus /usr/local/bin/
# cp eibtrace/eibtrace /usr/local/bin/
# cp firereads/firereads /usr/local/bin/
# cp readmemory/readmemory /usr/local/bin/
# cp resetdevice/resetdevice /usr/local/bin/
# cp search/search /usr/local/bin/
# cp writememory/writememory /usr/local/bin/

eibtrace est l’équivalent de groupsocketlisten d’eibd.
eibcommand est l’équivalent groupwrite d’eibd.
eibread est l’équivalent groupread d’eibd.
A noter que groupread, groupwrite, groupswrite, groupsocketlisten et compagnie sont compatible avec eibnetmux.

La librairie PHP se trouve /usr/src/eibnetmux-2.0.1/client_lib/php/eibnetmux.php et les commandes getstatus.php readgroup.php writegroup.php dans /usr/src/eibnetmuxclientsamples-1.7.1/php , je me garde ça sous le coude pour l’instant.

Test intermédiaire de lecture du bus KNX

Il est temps de tester eibnetmux, et ses commandes.
L’IP de mon interface IP/KNX est 192.168.0.51.

# eibnetmux -s -t -u -e -d --pidfile=/var/run/eibnetmux.pid 192.168.0.51 
# ps aux | grep eibnetmux
root 1993 0.0 0.0 3152 912 ? Ss 17:02 0:00 eibnetmux -s -t -u -e -d --pidfile=/var/run/eibnetmux.pid 192.168.0.51
root 2067 0.0 0.0 4060 820 pts/0 S+ 17:20 0:00 grep eibnetmux

Tâchons d’écouter ce qu’il se passe sur le bus :

# eibtrace 127.0.0.1
Connection to eibnetmux '127.0.0.1' established

Puis dans un autre shell, allumons et éteignons la lumière (groupe d’adresse 0/0/1 comme indiqué au début) :

# eibcommand -s 127.0.0.1 0/0/1 1 1
# eibcommand -s 127.0.0.1 0/0/1 1 0

Ce qui renvoit dans notre eibtrace :

2013/04/18 22:38:45:640 – phys addr: 0.2.189 – IND low W group addr: 0/0/1 – value: 1 | 1 | 1 | 1 (81 – eis types: 1, 2, 7, 8)
2013/04/18 22:38:45:686 – phys addr: 1.1.2 – IND low W group addr: 0/0/1 – value: 1 | 1 | 1 | 1 (81 – eis types: 1, 2, 7, 8)
2013/04/18 22:38:45:741 – phys addr: 1.1.2 – IND low W group addr: 0/0/2 – value: 65 | 168 (a8 – eis types: 6, 14)

Puis

2013/04/18 22:38:54:278 – phys addr: 0.2.189 – IND low W group addr: 0/0/1 – value: 0 | 0 | 0 | 0 (80 – eis types: 1, 2, 7, 8)
2013/04/18 22:38:54:366 – phys addr: 1.1.2 – IND low W group addr: 0/0/1 – value: 0 | 0 | 0 | 0 (80 – eis types: 1, 2, 7, 8)
2013/04/18 22:38:54:432 – phys addr: 1.1.2 – IND low W group addr: 0/0/2 – value: 0 | 0 (00 – eis types: 6, 14)

A noter, que sans modifier le ficher eibtrace.c avant sa compilation, nous aurions eu ceci :

2013/04/14 17:28:43:570 – 0.2.189 IND low W 0/0/1 : on | 1 | 1 | 1 (81 – eis types: 1, 2, 7, 8)
2013/04/14 17:28:43:614 – 1.1.2 IND low W 0/0/1 : on | 1 | 1 | 1 (81 – eis types: 1, 2, 7, 8)
2013/04/14 17:28:43:671 – 1.1.2 IND low W 0/0/2 : 65% | 168 (a8 – eis types: 6, 14)

Puis

2013/04/14 17:29:07:316 – 0.2.189 IND low W 0/0/1 : off | 0 | 0 | 0 (80 – eis types: 1, 2, 7, 8)
2013/04/14 17:29:07:403 – 1.1.2 IND low W 0/0/1 : off | 0 | 0 | 0 (80 – eis types: 1, 2, 7, 8)
2013/04/14 17:29:07:480 – 1.1.2 IND low W 0/0/2 : 0% | 0 (00 – eis types: 6, 14)

Pensez à faire un killall eibnetmux.
Bravo, on vient de faire un groupswrite : eibcommand -s <serveur> <group address> <type eis> <valeur>

Avec eibtrace, on trace les valeurs lues sur le bus KNX, lampe allumée, variateur à 65%, puis lampe éteinte, variateur à 0%.
0.2.189 correspond à ma passerelle IP/KNX, 1.1.2 à mon TXA213.
Si l’ordre provient d’un interrupteur, le phénomène est identique.

Ecoute du bus avec eibtrace

Ecoute du bus avec eibtrace

La suite consiste à avaler puis digérer ces valeurs.

Absorbtion des valeurs du bux KNX

J’ai besoin de php5 + mysql-server et tant qu’à faire, apache 2 pour la visualisation des lumières :

# apt-get install php5 php5-cli php5-mysql libapache2-mod-php5 php5-dev apache2 mysql-server php-pear

Normalement, une partie de ces paquets devraient déjà être installé avec l’installation d’eibnetmux.

Mon mot de passe mysql pour suivre cet article : dbpass

Pour les plus « doués », je conseille quelque chose de plus léger qu’Apache2 sur Raspberry Pi, genre Lighttpd, Cherokee, Hiawatha.

Le script d’ init.d pour eibnetmux s’illustre d’une particularité à la ligne 41, en plus de démarrer eibnetmux sur mon interface IP Siemens N146 5WG1 146-1AB01 (192.168.0.51), il lance en fond de tâche un « eibtrace 127.0.0.1 » vers le fichier /tmp/eibtrace . Tout ce qui se passera à partir de l’exécution d’eibnetmux sera loggé dans le fichier /tmp/eibtrace .
Note : sans l’ajout de « fflush(stdout); » sans eibtrace.c, la redirection stdout ne fonctionne pas.

# vi /etc/init.d/eibnetmux

Qui contient :

#! /bin/sh
### BEGIN INIT INFO
# Provides: eibnetmux
# Required-Start: mysql
# Required-Stop: mysql
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start eibnetmux service at the end of boot
# Description: This services is for communications with knx/eib.
### END INIT INFO

# by Lionel @ domolio.fr

PATH=/sbin:/usr/sbin:/bin:/usr/bin
NAME=eibnetmux
DAEMON=/usr/local/bin/eibnetmux
DAEMON_ARGS="-s -t -u -e -d --pidfile=/var/run/eibnetmux.pid 192.168.0.51"
PIDFILE=/var/run/eibnetmux.pid

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

if [ ! -x $DAEMON ]; then
 echo "eibnetmux appears to be uninstalled."
fi

#
# Function that starts the daemon/service
#
do_start()
{
echo -n "Starting eibnetmux"
/usr/local/bin/eibnetmux $DAEMON_ARGS
echo " done"
sleep 2
echo -n "Starting eibtrace"
/usr/local/bin/eibtrace 127.0.0.1 > /tmp/eibtrace &
echo " done"
}

do_stop()
{
echo -n "Stoping eibnetmux"
PID=`cat $PIDFILE`
kill $PID &> /dev/null
echo " done"
}

#
# Function that stops the daemon/service
#

case "$1" in
 start)
 do_start
 ;;
 stop)
 do_stop
 ;;
 restart)
 do_stop
 sleep 1
 do_start
 ;;
 status)
 pid=$(pidofproc -p $PIDFILE $DAEMON)
 ret=$?
 pid=${pid% } # pidofproc() supplies a trailing space, strip it

if [ $ret -eq 0 ]; then
 echo "eibnetmux is running (PID: $pid)"
 exit 0
 elif [ $ret -eq 1 ] || [ $ret -eq 2 ]; then
 echo "eibnetmux is dead, although $PIDFILE exists."
 exit 1
 elif [ $ret -eq 3 ]; then
 echo "eibnetmux is not running."
 exit 3
 fi
 echo "sais pas"
 ;;
 *)
 echo "usage: $0 {start|stop|restart|status}"
 exit 1
esac
# chmod +x /etc/init.d/eibnetmux
# insserv eibnetmux

A ce stade, j’ai un raspberry capable d’écouter et de commander mon bus KNX, je vais y rajouter ma sauce « home made » pour lire et écrire comme je l’entends.
Je le fais en PHP, parce que c’est un des seuls languages que je connais 🙂
J’installe le paquet php-pear afin d’installer System_Daemon pour me permettre de daemoniser un script PHP et d’avoir des logs.

# pear install -f System_Daemon

Lire le très bon article de Kevin van Zonneveld : Create daemon in PHP.

Le principe

Une fonction forte utile : tail ; bien connue des utilisateurs UNIX, mais pour l’utiliser en PHP, j’utilise le script dispo sur le book php : http://php.net/manual/fr/function.inotify-init.php
Comme signalé dans le premier commentaire, le résultat est identique à un « tail -f » exécuté dans un shell.
J’avais déjà utilisé la commande unix logtail pour arriver à mes fins dans un script permettant de commander un bandeau LED RGB via KNX, toujours en exploitant les logs.
Communication entre un bus KNX et un serveur linux, avec cette fonction PHP, c’est plus propre.

Ces deux outils vont me permettre de faire de mon script un vrai « service » sur mon Rapsberry Pi.
Il va me permettre d’avoir des logs, un service propre à la communication KNX ↔ Raspberry Pi.

Le but étant d’écouter tout ce qui se passe sur le bus (via eibtrace) et de l’écrire dans un fichier.

Eibtrace log dans un fichier

Eibtrace log dans un fichier

Puis, de « parser » ce fichier pour que chaque action qui nous intéresse soit retranscrite dans une table MySQL.
Vient enfin une page qui consulte cette base MySQL, donc : l’état de mes intervenants KNX.

Nous devons installer l’extention php inotify, puis l’activer :

# pecl install inotify
# vi /etc/php5/conf.d/30-inotify.ini

Pour y insérer :

extension=inotify.so

Mise en place

Structure de la base de données

Pourquoi faire simple quand on peut faire compliquer ?
Par souplesse, je split mes données en 2 tables :
– La première regroupe les Group Address → knx_ga .
– La secondes regroupe les EIS possible → knx_eis.

Ma base s’appelle domy.
Un mysqldump :

--
-- Table structure for table `knx_ga`
--

DROP TABLE IF EXISTS `knx_ga`;
CREATE TABLE `knx_ga` (
  `ga_id` int(3) NOT NULL AUTO_INCREMENT,
  `ga_groupaddress` tinytext NOT NULL,
  `ga_eis_id` int(3) NOT NULL,
  `ga_name` mediumtext NOT NULL,
  `ga_value` text NOT NULL,
  `ga_comment` text NOT NULL,
  PRIMARY KEY (`ga_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

--
-- Table structure for table `knx_eis`
--

DROP TABLE IF EXISTS `knx_eis`;
CREATE TABLE `knx_eis` (
  `eis_id` int(3) NOT NULL AUTO_INCREMENT,
  `eis_code` tinytext NOT NULL,
  `eis_num` int(3) NOT NULL,
  `eis_type` tinytext NOT NULL,
  PRIMARY KEY (`eis_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `knx_eis`
--

LOCK TABLES `knx_eis` WRITE;
/*!40000 ALTER TABLE `knx_eis` DISABLE KEYS */;
INSERT INTO `knx_eis` VALUES (1,'1.001',1,'Off / Off'),(2,'5.001',2,'Pourcentage');
/*!40000 ALTER TABLE `knx_eis` ENABLE KEYS */;
UNLOCK TABLES;

La table knx_eis contient le numéro de type d’eis, le type de datapoint, et un petit commentaire.
Une fois importé, je renseigne mon premier Group Address du bux KNX, le 0/0/1, correspondant au On/Off + indicateur d’état.

INSERT INTO `domy`.`knx_ga` (`ga_id`, `ga_groupaddress`, `ga_eis_id`, `ga_name`, `ga_value`, `ga_comment`) VALUES (NULL, '0/0/1', '1', 'lampe1_onoff', '0', 'Lampe 1');

Idem avec mon GA 0/0/2, correspondant à la valeur d’éclairage, pour rappel, il s’agit d’un variateur TXA213.

INSERT INTO `domy`.`knx_ga` (`ga_id`, `ga_groupaddress`, `ga_eis_id`, `ga_name`, `ga_value`, `ga_comment`) VALUES (NULL, '0/0/2', '2', 'lampe1_eclairage', '0', 'Lampe 1 : valeur éclairement');

Le champs de la table qui va changer, c’est ga_value, il passera à 1 lorsque la lumière est allumée, à 0 lorsqu’elle est éteinte.
Pour l’éclairage, une valeur entre 0 et 100.
Et voila, les racines sont là, il reste à remplir ces données et les exploiter.

knx-tail2mysql : parcourir l’activité du bus KNX vers table MySQL

Vous mélangez le script System_Daemon + Log Tail + un peu de MySQL pour obtenir ce script (pensez à cliquer pour tout dérouler)

# touch /usr/local/bin/knx-tail2mysql
# chmod +x /usr/local/bin/knx-tail2mysql
# vi /usr/local/bin/knx-tail2mysql

Script qui contient :

#!/usr/bin/php -q
<?php
// --------------------------------------
// --       Daemonise PHP script       --
// --------------------------------------
// D'après http://kvz.io/blog/2009/01/09/create-daemons-in-php/
// Allowed arguments & their defaults
 
$runmode = array(
    'no-daemon' => false,
    'help' => false,
    'write-initd' => false,
);
 
// Scan command line attributes for allowed arguments
foreach ($argv as $k=>$arg) {
    if (substr($arg, 0, 2) == '--' && isset($runmode[substr($arg, 2)])) {
        $runmode[substr($arg, 2)] = true;
    }
}

// Help mode. Shows allowed argumentents and quit directly
if ($runmode['help'] == true) {
    echo 'Usage: '.$argv[0].' [runmode]' . "\n";
    echo 'Available runmodes:' . "\n";
    foreach ($runmode as $runmod=>$val) {
        echo ' --'.$runmod . "\n";
    }
    die();
}

// Make it possible to test in source directory
// This is for PEAR developers only
ini_set('include_path', ini_get('include_path').':..');

// Include Class
error_reporting(E_STRICT);
require_once 'System/Daemon.php';

// Setup
$options = array(
    'appName' => 'knx-tail2mysql',
    'appDir' => dirname(__FILE__),
    'appDescription' => 'Parses KNX logfiles and stores them in MySQL',
    'authorName' => 'Lionel',
    'authorEmail' => 'lionel@chocolio.com',
    'sysMaxExecutionTime' => '0',
    'sysMaxInputTime' => '0',
    'sysMemoryLimit' => '1024M',
    'appRunAsGID' => 0,
    'appRunAsUID' => 0,
);

System_Daemon::setOptions($options);

// This program can also be run in the forground with runmode --no-daemon
if (!$runmode['no-daemon']) {
    // Spawn Daemon
    System_Daemon::start();
}

// With the runmode --write-initd, this program can automatically write a
// system startup file called: 'init.d'
// This will make sure your daemon will be started on reboot
if (!$runmode['write-initd']) {
    System_Daemon::info('not writing an init.d script this time');
} else {
    if (($initd_location = System_Daemon::writeAutoRun()) === false) {
        System_Daemon::notice('unable to write init.d script');
    } else {
        System_Daemon::info(
            'sucessfully written startup script: %s',
            $initd_location
        );
    }
}

// --------------------------------------
// --            function tail         --
// --------------------------------------

// D'après http://php.net/manual/fr/function.inotify-init.php

function tail($file,&$pos) {
    // get the size of the file
    if(!$pos) $pos = filesize($file);
    // Open an inotify instance
    $fd = inotify_init();
    // Watch $file for changes.
    $watch_descriptor = inotify_add_watch($fd, $file, IN_ALL_EVENTS);
    // Loop forever (breaks are below)
    while (true) {
        // Read events (inotify_read is blocking!)
        $events = inotify_read($fd);
        // Loop though the events which occured
        foreach ($events as $event=>$evdetails) {
            // React on the event type
            switch (true) {
                // File was modified
                case ($evdetails['mask'] & IN_MODIFY):
                    // Stop watching $file for changes
                    inotify_rm_watch($fd, $watch_descriptor);
                    // Close the inotify instance
                    fclose($fd);
                    // open the file
                    $fp = fopen($file,'r');
                    if (!$fp) return false;
                    // seek to the last EOF position
                    fseek($fp,$pos);
                    // read until EOF
                    while (!feof($fp)) {
                        $buf .= fread($fp,8192);
                    }
                    // save the new EOF to $pos
                    $pos = ftell($fp); // (remember: $pos is called by reference)
                    // close the file pointer
                    fclose($fp);
                    // return the new data and leave the function
                    return $buf;
                    // be a nice guy and program good code <img class="wp-smiley" alt=";-)" src="https://www.domolio.fr/wp-includes/images/smilies/icon_wink.gif" />
                    break;
                    // File was moved or deleted
                case ($evdetails['mask'] & IN_MOVE):
                case ($evdetails['mask'] & IN_MOVE_SELF):
                case ($evdetails['mask'] & IN_DELETE):
                case ($evdetails['mask'] & IN_DELETE_SELF):
                    // Stop watching $file for changes
                    inotify_rm_watch($fd, $watch_descriptor);
                    // Close the inotify instance
                    fclose($fd);
                    // Return a failure
                    return false;
                    break;
            }
        }
    }
}

// ------------------------------------------
// --      MON CODE PERSO COMMENCE ICI     --
// ------------------------------------------

// Connexion avec la base de données mysql
// Egalement possible de faire un include
$MYSQLHOST      = "localhost";
$MYSQLLOGIN     = "root";
$MYSQLPWD       = "dbpass";
$MYSQLBASE      = "domy";
$db = mysql_connect($MYSQLHOST, $MYSQLLOGIN, $MYSQLPWD);
$mysql=mysql_select_db($MYSQLBASE,$db);

if ($mysql!=1) {
  System_Daemon::notice('La connection avec la base de données a échoué.');
  exit();
}

// ---
// D'après http://stackoverflow.com/questions/9668299/extract-part-of-string-with-php
function get_string_between($string, $start, $end){
    $string = " ".$string;
    $ini = strpos($string,$start);
    if ($ini == 0) return "";
    $ini += strlen($start);
    $len = strpos($string,$end,$ini) - $ini;
    return trim(substr($string,$ini,$len));
}

// ---
// Quels sont les GA à surveiller ?

$req_sel_ga     = "SELECT ga_id,ga_groupaddress FROM knx_ga";
$qur_sel_ga     = mysql_query($req_sel_ga) or die (mysql_error());
$ga_bdd         = array();
while($dat_sel_ga = mysql_fetch_array($qur_sel_ga)) {
        $ga_id          = $dat_sel_ga['ga_id'];
        $ga_groupaddress        = $dat_sel_ga['ga_groupaddress'];
        $ga_bdd[$ga_groupaddress]       = $ga_id;
}
// ---

// ---
// parse/tail du fichier du eibtrace
$lastpos = 0;
while (true) {
	// On tail le fichier de log
	$knxlisten = tail("/tmp/eibtrace",$lastpos);
	// On réagit dès qu'on a un Write
	// Pour chaque ligne, on récupère le Groupe d'Addresse et de la valeur qu'on converti
	System_Daemon::notice($knxlisten);
	$groupaddr	= get_string_between($knxlisten,'group addr: ',' -');
	$value		= get_string_between($knxlisten,'value: ',' |');
	System_Daemon::notice("GA : ".$groupaddr." | VALUE : ".$value);
	// on regarde si ca fait partit des elements à surveiller
	if (array_key_exists($groupaddr, $ga_bdd)) {
                        // la valeur associé = l'id dans la BDD
                        $ga_id_update   = $ga_bdd[$groupaddr];
                        //System_Daemon::info($groupaddr." est à surveiller. Mise à jour de sa valeur dans la BDD");
                        System_Daemon::info($groupaddr." -> ".$value);
                        $req_sel_ga_update      = "UPDATE knx_ga SET ga_value = '$value' WHERE ga_id = $ga_id_update";
                        //System_Daemon::info("Requete SQL -> ".$req_sel_ga_update);
                        // Et on update la BDD
                        mysql_query($req_sel_ga_update);
                }
}

?>

Ici, les informations de connexion à la base MySQL sont en dur, à partir de la ligne 143.
On notera le chemin du fichier à parser à la ligne 186.

Egalement ici, on se rend compte de modifier eibtrace, par simplicité, en effet, une ligne de log se présente ainsi :
2013/04/18 22:38:45:741 – phys addr:    1.1.2 – IND low    W group addr:    0/0/2 value: 65 | 168 (a8  – eis types: 6, 14)
Le script récupère ce qu’il y’a entre « group addr » et « « , puis entre « value: » et « |« . Plus simple …

Un petit test … Il est nécessaire d’avoir le script init.d/eibnetmux de lancé avec eibtrace qui redirige vers /tmp/eibtrace.

# knx-tail2mysql
[Apr 14 22:53:22] notice: Starting knx-tail2mysql daemon, output in: '/var/log/knx-tail2mysql.log'
# cat /var/log/knx-tail2mysql.log
[Apr 14 22:53:22] notice: Starting knx-tail2mysql daemon, output in: '/var/log/knx-tail2mysql.log'
[Apr 14 22:53:22] info: Changed identify to 'root':'root'
[Apr 14 22:53:22] info: not writing an init.d script this time

Tout va bien … Tuez le processus si il est en fond de tâche.

Script de démarrage

Le script se lance en tant que daemon, pour ne pas oublier, faisons un petit init.d script et le logrotate:

# knx-tail2mysql --write-initd

Et il vous pond un script init.d ! magique !

# vi /etc/init.d/knx-tail2mysql

Une petite modification malgré tout, afin de s’assurer que le parse du fichier de traces se lance après que la connexion au bus soit effective, et donc fichier crée.
Sans quoi, il se lance avant même que mysql ne soit lancé…

# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs

Deviens :

# Required-Start:    eibnetmux
# Required-Stop:     eibnetmux

Et on l’installe en tant que script de démarrage :

# insserv knx-tail2mysql

Logrotate

Coté logrotate, l’on crée un script dans le dossier /etc/logrotate.d/ qui sera automatiquement traité quotidiennement, généralement à 06h25.

# vi /etc/logrotate.d/knx-tail2mysql

Contient :

/var/log/knx-tail2mysql.log {
        weekly
        missingok
        rotate 12
        compress
        delaycompress
        notifempty
        sharedscripts
        postrotate
                /etc/init.d/knx-tail2mysql restart > /dev/null
        endscript
}
# ls -lh /var/log/knx-tail2mysql.log*
-rw-r--r-- 1 root root 449 févr. 21 00:20 /var/log/knx-tail2mysql.log
# logrotate -f /etc/logrotate.d/knx-tail2mysql
# ls -lh /var/log/knx-tail2mysql.log*
-rw-r--r-- 1 root root 306 févr. 21 00:21 /var/log/knx-tail2mysql.log
-rw-r--r-- 1 root root 449 févr. 21 00:20 /var/log/knx-tail2mysql.log.1

L’on passe d’un fichier à deux fichiers, les suivants seront compressés, ce logrotate fonctionne.

Essai d’exécution

Eibtrace doit être en route en fond de tâche (les scripts précédents le lance en même temps qu ‘eibnetmux), avec écriture de la trace dans le fichier /tmp/eibtrace .
Un petit init 6 c’est bien aussi.
On lance knx-tail2mysql et on vérifie qu’un processus tourne en fond de tâche :

# knx-tail2mysql
[Apr 14 23:33:27] notice: Starting knx-tail2mysql daemon, output in: '/var/log/knx-tail2mysql.log'
# ps aux | grep knx-tail2mysql
root 3163 0.2 0.4 39608 5004 pts/0 S 23:33 0:00 /usr/bin/php -q /usr/local/bin/knx-tail2mysql
root 3168 0.0 0.0 4060 816 pts/0 S+ 23:33 0:00 grep knx-tail2mysql

Process en fond de tâche : OK

Si ce n’est pas le cas, et que aucune erreur n’est donnée dans le fichier de log, c’est peut-être que vous n’avez pas activé l’extension inotify.ini.
Pour débugger davantage, placer des System_Daemon::notice(« bla bla bla »);

J’allume ma lampe, en ligne de commande, via un interupteur, le résultat est le même.

# eibcommand -s 127.0.0.1 0/0/1 1 1
# cat /tmp/eibtrace
2013/04/18 22:58:57:598 - phys addr: 0.2.189 - IND low W group addr: 0/0/1 - value: 1 | 1 | 1 | 1 (81 - eis types: 1, 2, 7, 8)
2013/04/18 22:58:57:651 - phys addr: 1.1.2 - IND low W group addr: 0/0/1 - value: 1 | 1 | 1 | 1 (81 - eis types: 1, 2, 7, 8)
2013/04/18 22:58:57:708 - phys addr: 1.1.2 - IND low W group addr: 0/0/2 - value: 65 | 168 (a8 - eis types: 6, 14)

Trace dans le fichier : OK

Normalement, la table s’est mise à jour.

# mysql -pdbpass domy -e "SELECT ga_groupaddress,ga_value FROM knx_ga;"
+-------------------+-------------+
| ga_groupaddress   | ga_value   |
+-------------------+-------------+
| 0/0/1             | 1          |
| 0/0/2             | 65         |
+-------------------+-------------+

Trace dans le fichier : OK

Si la table MySQL ne se met pas à jour, mais que le fichier /tmp/eibtrace est à jour, consulter le fichier de log /var/log/knx-tail2mysql.log :

warning: [PHP Warning] filesize(): stat failed for /tmp/eibtrace [l:86]
warning: [PHP Warning] inotify_add_watch(): No such file or directory [l:90]

Alors que le fichier existe et que knx-tail2mysql tourne.
C’est probablement que l’ordre initialisation des scripts est incorrect.

OK, OK, OK ! L’extinction de la lampe, même effet, parfait, on continue !

Schema avec knx-tail2mysql

Schema avec knx-tail2mysql

Visualisation et contrôle par interface web

A ce stade, on a une table MySQL qui se met à jour selon l’état des actionneurs.
Qu’est-ce qui permet d’afficher en quasi-instantanné le contenu des champs MySQL ?
L’ajax voyons ! Tant mieux, je suis nul en AJAX !

Dans le cadre de gestion du lumière, il y’a 3 actions principales, donc 3 scripts vitaux :
– Récupérer l’état on/off ou la valeur d’éclairage.
– Envoyer un toggle on/off.
– Envoyer une valeur d’éclairage.

Je n’ai pas de volet roulant ou de gestion de chauffage, évidemment, plus il y’a de types d’élements, plus ça se complique ; j’ai voulu séparer dans une autre table les EIS pour cette raison , mais pour l’instant on va s’appliquer à allumer, éteindre et changer la valeur d’éclairage de mon ampoule sur le Hager TXA213.

J’ai choisi d’utiliser jQuery pour communiquer en AJAX, et ainsi profiter de la librairie JQuery-UI pour ce qui est graphique, slider, etc…
jQuery me permettra de travailler avec des noms pour appeler mes lumière, lamp1_onoff, lampe1_eclairage, lampe2cuisine_onoff, etc.. d’où le champs ga_name dans la table knx_ga.
Puis jQuery me permettra également d’utiliser JQuery Mobile pour les mêmes fonctions mais sur mobile.
J’utilise une classe PHP pour débugger, c’est écrit par Joe Fallon et ça s’appel PopupPhpDebug.

Deux div ID, l’un pour une image on/off, l’autre pour un slider avec la valeur d’éclairage.

Les fichiers sont téléchargables ici :
– Pensez à supprimer votre index.html dans /var/www/
– Conservez les droits www-data:www-data sur les fichiers et répertoires.

Telecharger

Je ne vais pas faire de cours de PHP, juste expliquer les grandes lignes du fonctionnement de mon interface web.

De l’AJAX pour piloter une lumière

Un simple div pour une simple lumière :

<img id="toggle_light-lampe1_onoff" alt="chargement" src="images/loading.gif" />

Dans l’attribut id :
toggle_ : sert de préfixe, tout ce qui est toggle_ correspond à une lumière.
lampe1_onoff : nom de la correspondance via ma table MySQL -> 0/0/1 dans ce cas.
Ainsi, autant toggle_* qu’il a de lumière.

Dans le même principe :

<div id="slider-lampe1_eclairage"></div>
<div id="text-lampe1_eclairage" align="center"></div>

slider-* pour un slider à les valeurs variables.
text-* pour afficher la valeur.

Interface jQuery pour KNX

Interface jQuery pour KNX

Et pour contrôler tout ça :


$(function() {
var intervalrefresh = 1000;

// fonction qui recupere la valeur d'un objet selon le nom du GA
$.get_light_value = function(light_name) {
 var result = null
 $.ajax({
 url: 'ajax/knx-get_light_value.php',
 data: 'ga_name='+light_name,
 dataType: 'json',
 async: false,
 success: function(data) {
 result = data['value'];
 //console.log("Valeur de : "+light_name+" -> "+result );
 }
 });
 return result;
}

// fonction qui toggle la valeur d'un object son le nom du GA (on/off)
$.set_light_toggle = function(light_name) {
 $.ajax({
 url: 'ajax/knx-set_light_toggle.php',
 data: 'ga_name='+light_name,
 dataType: 'json',
 async: false,
 success: function(data) {
 //console.log("Mise à jour de : "+light_name);
 }
 });
}

// fonction qui envois une valeur à un GA
$.set_light_value = function(light_name,value) {
 $.ajax({
 url: 'ajax/knx-set_light_value.php',
 data: 'ga_name='+light_name+'&ga_value='+value,
 dataType: 'json',
 async: false,
 success: function(data) {
 //console.log("Mise à jour de : "+light_name);
 }
 });
}

$(document).ready(function(){
 var refreshId = setInterval( function(){

// Refresh des lights
 $('[id^="toggle_light-"]').each(function() {
 var light_name_split = $(this).attr('id').split('-');
 var light_name = light_name_split[1];
 var light_value = $.get_light_value(light_name);
 if (light_value == 1) $('#toggle_light-'+light_name).attr('src',"images/lampes-on.png");
 if (light_value == 0) $('#toggle_light-'+light_name).attr('src',"images/lampes-off.png");
 });

// Refresh des sliders
 $('[id^="slider-"]').each(function() {
 var light_name_split = $(this).attr('id').split('-');
 var light_name = light_name_split[1];
 var light_value = $.get_light_value(light_name);
 $(this).slider( "option", "value", light_value);
 $('#text-'+light_name).html(light_value+"%");

});

}, intervalrefresh);
});

// mise à jour du bus KNX après mouvement du slider
 $('[id^="slider-"]').each(function() {
 var light_name_split = $(this).attr('id').split('-');
 var light_name = light_name_split[1];
 $(this).slider({
 max: 100,
 min: 0,
 stop: function(event,ui) {
 //console.log("nouvelle valeur du slider : "+ui.value);
 $.set_light_value(light_name,ui.value);
 }
 });
 });

// mise à jour des lumières après un click
 $('[id^="toggle_light-"]').click(function() {
 var light_name_split = $(this).attr('id').split('-');
 var light_name = light_name_split[1];
 $.set_light_toggle(light_name);
 });

// fin
});

Oula !
En gros, ça dit que toutes les 1000 ms secondes (1 seconde), pour chaque div qui commence par toggle_ d’executer le fichier ajax/knx-get_light_value.php , qui lui contient (via des includes et functions) une requête MySQL pour chercher la valeur correspondante en base.
Si c’est égal à 1, ça affiche une ampoule jaune, si c’est égal à 0, ça affiche une ampoule grise.
Idem pour le slider, on place le curseur à la valeur correspondante avec affichage sous forme texte.

Tandis qu’un click sur une ampoule, donc un div, a pour action d’exécuter le fichier ajax/knx-set_light_toggle.php , qui lui contient une récupèration de la valeur en base, il l’inverse, et l’applique sur le bus KNX.
Il l’applique sur le bus KNX via la librairie eibnetmux.php, souvenez vous, nous avions compilé eibnetmux avec les librairies PHP, c’est justement là qu’elle nous sert !

Le retour d’état de l’actionneur se fait par le cheminement eibtrace, knx-tail2mysql, ajax ; pas de « mise à jour directe », on évite ainsi les erreurs possibles, mais du coup, l’image s’actualise au pire qu’une seconde plus tard (+ temps de traitement de l’info), d’où le « quasi-instantanné ».

Schéma interaction KNX avec PHP

Schéma interaction KNX avec PHP

Ca marche bien !

Firebug pour surveiller l'AJAX

Firebug pour surveiller l’AJAX

La console firebug permet de visualiser les transactions AJAX -> MySQL, rajoutez des debugs si nécessaire.
Il est possible de diminuer les 1000ms pour obtenir plus de réactivité, c’est au serveur MySQL de pouvoir encaisser.

On peut également faire de l’image mapping sur une photo, grace à des outils tel que http://www.image-maps.com on définit un rectangle sur une lampe, modifie le code HTML pour placer notre « id ».

Créez votre map

Créez votre map

L’outil sert surtout pour créer la zonne au bon endroit.
Le code modifié :

<img id="Image-Maps_8201304191538462" alt="" src="http://www.image-maps.com/uploaded_files/8201304191538462_sketchup.png" usemap="#Image-Maps_8201304191538462" width="716" height="531" border="0" />
<map id="_Image-Maps_8201304191538462" name="Image-Maps_8201304191538462">
<area id="toggle_light-lampe1_onoff" title="Allumer/eteindre" alt="Allumer/eteindre" coords="510,143,579,266" shape="rect" />
</map>

Et un clique sur l’abat-jour de l’image éteind/allume la lumière.

Click pour allumer/eteindre

Click pour allumer/eteindre

Il doit certaiement être possible de modifier l’image de cette petite lampe pour qu’elle paraisse allumée.
Un autre exemple plus généraliste des maps sur image en CSS : cssplay.co.uk .

Les limites de la gestion de la maison deviennent celles du graphisme web, du moment où on a accès à l’état des éléments KNX, qu’on peut les piloter, techniquement c’est presque sans limite ; il faut savoir s’y faire ergonomiquement, c’est essentiel.

Interface mobile pour téléphone et tablette

Pour l’instant, c’est très brouillon, pas d’AJAX, je pars du principe que si je contrôle ma maison avec mon smartphone, c’est parce que je ne suis pas chez moi, donc pas de rafraichissement instantanné.
J’utilise jQuery Mobile, une demo est disponible sur le site officiel.
Mon utilisation est celle d’un formulaire traité en PHP classique, pas très au point pour l’instant, mais fonctionnel pour un début.

Il me semble qu’il est possible de convertir un site web en application iphone/android, il faut que je retrouve le nom de cet outil.
A terme, le tout protégé par htacces ou authentification php.

Inteface mobile

Inteface mobile

Rendu et réactivité

Une vidéo afin de se rendre compte de la réactivité du click et de la remonté d ‘infos, malgré l’utilisation d’une webcam de piètre qualité, avec une mise à niveau de la luminosité catastrophique, je n’ai pas trouvé mieux pour filmer la réaction du click sur la lampe.

Conclusion

Mon but étant d’arriver à contrôler l’installation domotique depuis un serveur par une interface web, c’est en bonne voie  !

Quelques points à approfondir lorsque j’aurai une installation KNX réele et complète :
– Groupe d’adresse différente entre l’état et l’action ? Vraiment ? Reste à voir comment gérer ça.
– Gestion des autres EIS : volets, BSO, chauffage, etc…
– Ajout d’intelligence avec du 1-wire.
– Une interface web ergonomiquement parfaite.

C’est relativement réactif, j’en attends pas plus pour l’instant.

Je n’utilise aucun cache EIBD, voir les commentaires sur l’article Se passer de linknx et webknx2 une fausse bonne idee ?

C’est donc une bonne base pour une plateforme de contrôle et supervision du bus KNX, j’ai hâte d’approfondir sur une installation réel .

Téléchargement

Je met à disposition une image de la carte SD de mon Raspberry Pi.
Attention, c’est très lourd : 7,42 Go. Sauvegardé avec Win32DiskImager, vous devriez pouvoir restaurer avec le même outil.

Mot de passe root : pi
Mot de passe MySQL : dbpass

Telechargerraspberry-domolio-knx.img : 7,42 Go
MD5 : 81a8df6724fea6c8916f6a8e814b908f

Have fun !

Posté dans Debian, KNX, php, Web | 52 Commentaires

Graphique de températures 1-wire avec pChart2

Il y’a quelques temps, j’ai abordé le sujet de la réalisation de graphiques de températures pour munin.
La base étant  l’exploitation des sondes 1-Wire sur une machine Debian et l’utilisation en PHP.
J’ai également parlé de la mise en base de données MySQL des valeurs du bus OneWire.

Un des buts de la mise en place des valeurs dans une base, est de pouvoir générer des graphiques personnalisés sur une durée et/ou une sonde spécifique.

Jusqu’à présent, j’avais une préférence pour les librairies Artichow, mais le projet a été arrêté.
Je me suis tourné vers pChart v2 : http://www.pchart.net

Ce que j’apprécie particulièrement, c’est la sandbox, sa documentation complète,ainsi que ses nombreuses possibilités !

Sandbox pChart

Sandbox pChart

En partant de mes derniers articles, j’ai repris un code généré en sandbox et adapté pour 24h de données 1-wire :
Script encore une fois, à adapter, je n’ai pas fait appel à mes includes pour mieux comprendre le principe du script.

<?php
ini_set('display_errors','Off');

// Préfixe de toutes les tables du site
$MYSQLHOST = "localhost";
$MYSQLLOGIN = "root";
$MYSQLPWD = "toto";
$MYSQLBASE = "1wire";
// Conection avec la base de données mysql
$db = mysql_connect($MYSQLHOST, $MYSQLLOGIN, $MYSQLPWD);
$mysql=mysql_select_db($MYSQLBASE,$db);

function OWSensorList($type=null) {
 $OWSensorList = array();
 $cpt = 0;
 if ($type == 'temperature') $req_owlist = "SELECT * FROM 1wire_sensor WHERE 1wire_sensor_type='temperature' ORDER BY 1wire_sensor_id ASC";
 else $req_owlist = "SELECT * FROM 1wire_sensor WHERE 1 ORDER BY 1wire_sensor_id ASC";
 $qur_owlist = mysql_query($req_owlist) or die(mysql_error());
 while($dat_owlist = mysql_fetch_array($qur_owlist)) {
 $OWSensorList[$cpt]['sensor_id'] = $dat_owlist['1wire_sensor_id'];
 $OWSensorList[$cpt]['sensor_enable'] = $dat_owlist['1wire_sensor_enable'];
 $OWSensorList[$cpt]['sensor_type'] = $dat_owlist['1wire_sensor_type'];
 $OWSensorList[$cpt]['sensor_family'] = $dat_owlist['1wire_sensor_family'];
 $OWSensorList[$cpt]['sensor_idaddress'] = $dat_owlist['1wire_sensor_idaddress'];
 $OWSensorList[$cpt]['sensor_comment'] = $dat_owlist['1wire_sensor_comment'];
 $cpt++;
 }
 return $OWSensorList;
}

// Retourne juste l'heure ou les minutes de YYYY-MM-DD H:i:s
function SplitTime($datemysql,$type) {
 list($date, $time) = explode(" ", $datemysql);
 list($year, $month, $day) = explode("-", $date);
 list($hour, $min, $sec) = explode(":", $time);
 if($type == 'min') return $min;
 if($type == 'hour') return $hour;
}

function OWFetch24HData($sensor_id) {
 $OWFetch24HData = array();
 $cpt = 0;
 $req_owlist = "SELECT * FROM 1wire_data WHERE 1wire_data_sensor_id = ".$sensor_id." AND 1wire_data_timestamp BETWEEN DATE_ADD( NOW( ) , INTERVAL -1 DAY ) AND NOW( ) ORDER BY 1wire_data_id ASC";
 $qur_owlist = mysql_query($req_owlist) or die(mysql_error());
 while($dat_owlist = mysql_fetch_array($qur_owlist)) {
 $fetch_timestamp = $dat_owlist['1wire_data_timestamp'];
 $fetch_minute = SplitTime($fetch_timestamp,'min');
 if($fetch_minute != '00') $OWFetch24HData['data_timestamp'][$cpt] = '';
 elseif($fetch_minute == '00') $OWFetch24HData['data_timestamp'][$cpt] = SplitTime($fetch_timestamp,'hour')."h";
 $OWFetch24HData['data_value'][$cpt] = $dat_owlist['1wire_data_value'];
 $cpt++;
 }
 return $OWFetch24HData;
}

include("lib/pChart2.1.3/class/pData.class.php");
include("lib/pChart2.1.3/class/pDraw.class.php");
include("lib/pChart2.1.3/class/pImage.class.php");

$myData = new pData();

$OWSensorList = OWSensorList('temperature');
for ($i = 0; $i < sizeof($OWSensorList); $i++) {
 if($OWSensorList[$i]['sensor_enable']) {
 $OWFetch24HData = OWFetch24HData($OWSensorList[$i]['sensor_id']);
 $myData->addPoints($OWFetch24HData['data_value'],$OWSensorList[$i]['sensor_id']);
 $myData->setSerieDescription($OWSensorList[$i]['sensor_id'],$OWSensorList[$i]['sensor_comment']);
 $myData->setSerieOnAxis($OWSensorList[$i]['sensor_id'],0);
 }
}

$myData->addPoints($OWFetch24HData['data_timestamp'],"Absissa");
$myData->setAbscissa("Absissa");

$myData->setAxisPosition(0,AXIS_POSITION_LEFT);
$myData->setAxisName(0,"Temp&eacute;ratures");
$myData->setAxisUnit(0,"°C");

$myPicture = new pImage(1000,400,$myData);
$myPicture->setShadow(TRUE,array("X"=>1,"Y"=>1,"R"=>50,"G"=>50,"B"=>50,"Alpha"=>20));

$myPicture->setFontProperties(array("FontName"=>"fonts/Forgotte.ttf","FontSize"=>18));
$TextSettings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE
, "R"=>0, "G"=>0, "B"=>0);
$myPicture->drawText(500,25,"Températures",$TextSettings);

$myPicture->setShadow(FALSE);
$myPicture->setGraphArea(75,50,975,360);
$myPicture->setFontProperties(array("R"=>0,"G"=>0,"B"=>0,"FontName"=>"fonts/Bedizen.ttf","FontSize"=>10));

$Settings = array("Pos"=>SCALE_POS_LEFTRIGHT
, "Mode"=>SCALE_MODE_FLOATING
, "LabelingMethod"=>LABELING_ALL
, "GridR"=>255, "GridG"=>255, "GridB"=>255, "GridAlpha"=>50, "TickR"=>0, "TickG"=>0, "TickB"=>0, "TickAlpha"=>50, "LabelRotation"=>0, "CycleBackground"=>1, "DrawXLines"=>1, "DrawSubTicks"=>1, "SubTickR"=>255, "SubTickG"=>0, "SubTickB"=>0, "SubTickAlpha"=>50, "DrawYLines"=>ALL);
$myPicture->drawScale($Settings);

$myPicture->setShadow(TRUE,array("X"=>1,"Y"=>1,"R"=>50,"G"=>50,"B"=>50,"Alpha"=>10));

$Config = "";
$myPicture->drawSplineChart($Config);

$Config = array("FontR"=>0, "FontG"=>0, "FontB"=>0, "FontName"=>"fonts/Forgotte.ttf", "FontSize"=>12, "Margin"=>6, "Alpha"=>30, "BoxSize"=>5, "Style"=>LEGEND_NOBORDER
, "Mode"=>LEGEND_HORIZONTAL
, "Family"=>LEGEND_FAMILY_LINE
);
$myPicture->drawLegend(837,16,$Config);

$myPicture->stroke();
?>

Il faut au moins 1h de données, résultat :

Graphique 1-wire avec librairie pChart

Graphique 1-wire avec librairie pChart

Comme d’habitude, il est nécessaire d’adapter, inclure, configurer, à chacun comme bon lui semble. Ça reste un exemple, ou une base de travail.

En tout cas, parmi les différentes libraries PHP pour génerer des graphiques, pChart2 est mon coup de coeur, même si le projet n’a pas bougé depuis septembre 2011, il est suffisament abouti.

Posté dans 1-wire, php, Web | 4 Commentaires

Acheter son matériel KNX

Près d’un an et demi que je m’équipe petit à petit de matériel KNX, faute à un chantier qui n’avance pas… J’ai eu l’opportunité de m’équiper en matériel KNX moins cher que ce que l’on peut trouver sur des sites e-commerce.

Où ça ? Ebay Allemagne.

En Allemagne, la domotique a un train d’avance, les chantiers sont plus souvent équipés en domotique, donc plus de revendeurs, plus de concurence, donc des prix plus bas qu’en France.
Etant en Alsace, c’est presque naturel d’aller voir les prix pratiqués chez nos voisins outre-Rhin.

Bref, voici le tour de matériel acquis au bout d’un an et demi d’achats sur eBay :

Matériel KNX acheté sur ebay

Matériel KNX acheté sur ebay

Voici les prix auxquels j’ai acheté ce matériel :

MatérielAcheté à
Schneider RegK/640mA : Alimentation 640mA60,00 €
Siemens N146 5WG1 146-1AB01 : Routeur IP/KNX157,00 €
Hager TXA112 : Alimentation 640mA190,00 €
Hager TXA213 : 3 sorties variation 300W208,00 €
Hager TXA213 : 3 sorties variation 300W202,22 €
Hager TXA213 : 3 sorties variation 300W174,00 €
Hager TXA213 : 3 sorties variation 300W160,00 €
Hager TXA207C : 10 sorties TOR204,95 €
Hager TXA207C : 10 sorties TOR202,50 €
Hager TXA207C : 10 sorties TOR255,99 €
Hager TXA227 : 8 sorties volets ou stores214,00 €
Hager TXA206C : 6 sorties TOR112,50 €
Hager TXA206C : 6 sorties TOR109,00 €
Hager TXB322 : 2 entrées32,50 €
Hager WKT302 : 2 boutons poussoir40,50 €
Hager TX450A : Controleur ambiance35,50 €
Siemens 5WG1 220-2AB3135,50 €
Total2394,16 €

2394,16 € étalé sur 1 an et demi, je ne l’imaginais pas !
Mon tableau hors-ligne, où je maintiens ces chiffres, comporte également des colonnes avec le prix constaté chez un revendeur allemand bien connu, le prix catalogue de la marque, ainsi que deux revendeurs français.
Cette même liste de matériel, m’aurait coûté :
Comparé au e-commerce allemand 4418 € soit 2024 € plus cher.
Comparé aux prix des sites constructeurs : 7522 € soit 5128 € d’économie.
Comparé au e-commerce français : 4677 € soit 2283 €d’économie.

Faire ses emplettes en allemagne, ne demande pas de connaissance en allemand, j’en ai aucune …
Parcontre, vaut mieux avoir un bon suivi des ventes, des frais de ports, et des accords pour l’expédition en France.
3/4 des annonces ebay.de ne mentionnent pas l’expédition de produits vers la France, mais 90% de ces même vendeurs sont prêts à vous l’expédier.
Ainsi, il faut gentillement demander si il est prêt à vous l’envoyer.

Pour gagner un précieux temps, je me suis fait un suivi des réponses des ebayers, car ce sont souvent les mêmes noms qui reviennent lors des ventes.

Suivi des ebayer

Suivi des ebayer

Evidement, ça reste de l’achat sur ebay, avec ses avantages : le prix, mais également avec ses incovénients : pas de SAV (quoi que … à voir …), la plupart du temps il faut payer par virement, délais de livraison plus long, matériel pas souvent neuf.
Ca reste le meilleur moyen de se monter une plateforme de test pour débuter en KNX.

Posté dans KNX | 31 Commentaires