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

Barrière infra-rouge, DS2401 et bus 1-wire

Après une longue pause de plusieurs mois, je me suis enfin attaqué à mon idée de barrière infra-rouge reliée au bus 1-wire.

Mon idée de base est d’être averti lors du passage du facteur : une boîte aux lettres domotisée.
Des solutions DIY existent déjà, regroupant des technologies d’ILS + IPX800RFXCOM, Zwave, etc…

Je n’ai pour l’instant pas lu d’articles utilisant le protocole 1-wire pour avertir de la venue du facteur, j’ai donc pensé à une solution pour y arriver.

Les solutions existantes pour l’instant se basent toutes sur la détection de l’ouverture de la porte ou du clapet de la boîte, il est clair que c’est le plus logique et évident ; sauf qu’en 1-Wire, surveiller l’omniprésence de la porte ou du clapet n’est pas envisageable car sur-occuperait l’ensemble du bus.
Le clapet de la boîte ne s’ouvre que pendant une demi-seconde et y placer une détection de la même façon qu’une fenêtre, n’est donc pas envisageable.

Le seul moyen, à mes yeux, est de surveiller le contenu de la boîte aux lettres.

Le petit matériel

Je me suis équipé de trois barrières infra-rouges ainsi que d’un relais 1 channel :

Barrière infra-rouge à 2,63 €

Barrière infra-rouge à 2,63 €

Cette barrière infrarouge dispose d’un récepteur / émetteur perpendiculaire au PCB.
A 2,63 € frais de ports compris, c’est le plus « cheap ».
3 pin :
– VCC (5V)
– Output
– Ground


Barrière infra-rouge à 7,41 €

Barrière infra-rouge à 7,41 €

Cette barrière infrarouge dispose d’un récepteur / émetteur parallèle au PCB.
A 2,63 € frais de ports compris, c’est le plus « cheap ».
4 pin :
– VCC (5V)
– Output
– Ground
– EN (???)


Barrière infra-rouge à 7,41 €

Barrière infra-rouge à 4,45 €

Cette barrière se trouve aux alentours de 4,45 €.
Elle est vendue en tant que barrière IR pour Arduino.
Contrairement à sa taille, son boîtier est un avantage.


Channel relais 5V

Channel relais 5V à 4,14 €

Un relais 5Volt monté sur un PCB, permettant de relier le DS2401 au bus 1-wire.


Schéma d'utilisation du DS2401

Schéma d’utilisation du DS2401

Un DS2401 déjà étudié pour la detection d’ouverture de portes et fenêtres.

Le principe

Le faisceau infra-rouge reflète sur une bande réfléchissante autocollante, le faisceau est renvoyé à la barrière infrarouge = il n’y a pas de courrier.

Boite aux lettres sans courrier

Boite aux lettres sans courrier

Le faisceau infra-rouge ne reflète pas, il est obstrué par une lettre ou un colis = il y’a du courrier.

Boite aux lettres avec courrier

Boite aux lettres avec courrier

Bon, alors … quelques points à préciser :

  • Je suis vraiment loin d’être un pro sous paint.
  • Je ne suis vraiment pas sûr que ça fonctionne, tout va dépendre de la sensibilité de la barrière IR (réglable avec un tournevis), mais faut bien essayer …
  • Ce n’est pas infaillible, si la lettre ne tombe pas devant le faisceau, c’est cuit, l’avantage c’est que le marabout du coin qui me laisse sa carte de visite ne me déclenchera pas d’alerte facteur.
  • Ce fonctionnement est applicable à d’autres cas : le chien est dans sa niche ? Les hirondelles dans leur nid ? Suffit d’une meilleure imagination.
  • Pas de boîtier adapté.
  • Un pétard dans la boîte aux lettres me rendrait fou de rage !
  • Faut être sûr d’avoir du 5 Volts qui tiennent jusqu’à la boîte aux lettres, malgré la paire torsadée.

Schéma électronique

Je pars avec mon existant, c’est à dire un injecteur 5V et un bus 1-wire.

Principe de fonctionnement barrière IR

Principe de fonctionnement barrière IR

J’alimente ma barrière infra-rouge, qui me sort du 5V sur la pin Output, cette même pin qui est reliée au Input du relais sur PCB.
En sortie du relais, je retrouve mon bus 1-wire avec mon DS2401.
La barrière infra-rouge va faire basculer mon relais, donc connecter ou déconnecter le DS2401.
Ainsi, logiciellement, j’aurais toute les 5 minutes par exemple, à tester la présence de ce DS2401 sur le bus pour y conclure l’état de la boîte aux lettres.

Pourquoi pas ?

Alors essayons ! Fil à l’air pour voir …
Humm…
Je rappelle que ce blog est alimenté par mes découvertes en domotique, j’ai des idées, je teste, je mets en ligne ; si il y a mieux, tant mieux … Ca fonctionne, c’est cool…
A ce stade je ne suis pas sûr que ça fonctionne dans un cas concret.

Les essais

Réglage du potentiomètre

Réglage du potentiomètre

Déjà les trois barrières infra-rouge, la puissance d’émission de la LED se régle par un potentiomètre.
C’est bien, mais les modèles sans boîtier ne sont pas faciles à régler, pas assez de sensibilité, c’est vite du tout ou rien.
Petite astuce : s’aider d’un appareil photo pour voir la lumière infrarouge s’atténuer selon la rotation du potentiomètre.

Photo produit

Photo produit

Ensuite le modèle à deux « potars » est encore moins facile d’utilisation.
C’est peut-être parce que je n’ai pas compris le chinois qui est écrit sur sa « photo de vente ».
J’ai l’impression que l’un sert à régler la puissance d’émission de la LED, et l’autre la sensibilité du phototransistor.
Le cavalier et la sortie « EN » je sèche…

Alors, fil en l’air, vite fait bien fait, ca donne ceci :

Montage fil à l'air n°1

Montage fil à l’air n°1

Rouge : 5V
Noir : masse
Blanc : Input/output entre la barrière et le switch, c’est ma commande.
Bleu et brun : Data 1-wire

C’est bien, mais le switch IR est instable, problème de sensibilité lié, mauvais positionnement de potentioètre?
Ca clignote ! grrr

En fait, ce qui ne va pas sur ce modèle de barrière, au delà de la sensibilité, c’est la tension de sortie en 3,3 Volts.

Le switch infra-rouge avec le boîtier jaune à 4,45 € a une commande à 5 Volts, bien plus pratique dans notre cas, et bien plus performant.
De plus, ce modèle fait l’objet d’une sensibilité de l’emetteur/recepteur beaucoup plus fine.

Pas besoin de plus de vidéo, ça fonctionne pour l’instant.

Coté OWHTTP également, le DS2401 est présent sur le bus lorsque le faisceau IR est obstrué ; à l’inverse, il est absent du bus lorsque le faisceau n’est pas obstrué.
La sensibilité d’obstruction est à régler selon la boîte aux lettres, selon le positionnement du switch, le type de réflecteur, l’utilisation d’un catadioptre ou non.

En pratique

En pratique ? Gros suspens !
Il y a une part de physique optique avec l’orientation et la sensibilité du faisceau IR.
Une part électronique avec l’arrivée du 1-WIRE et de son 5Volt injecté jusqu’à l’extérieur, dans une boîte aux lettres soumise aux intempéries. A voir …
L’article s’arrête malheureusement là, sans mise en oeuvre pratique pour l’instant, faute de cas concret : pas de boîte aux lettres, pas de boîtier pour planquer l’électronique.
J’essaie de récupérer une boîte aux lettres aux normes de La Poste pour y fixer de façon intelligente cette barrière IR, les réglages optiques fonctionnels et une programmation adéquate.

A suivre.

Posté dans 1-wire | 12 Commentaires

Interagir en jQuery/Ajax avec le bus KNX

Une semaine après mon article sur un frontend php  KNX.
Je bosse sur une interface simple pour visualiser et contrôler des points lumineux.

Pour l’instant, je fais au plus simple, j’ai deux points lumineux :
– Une ampoule sur un TXA213.
– Un bandeau LED RGB contrôlé par OLA.

Je pourrais également paramétrer d’autres ampoules sur mes TXA207C, mais je fais aussi du On/Off avec le TXA213.

J’ai fait un petit screencast aussi simplet que mes scripts, à regarder en 720p.

Il est difficile d’entrer dans les détails du script, cependant, le fonctionnement principal est lié à mon article précédent sur le bus KNX et l’enregistrement des valeurs dans la base MySQL.

La nouveauté provient des scripts jQuery et Ajax pour le rafraîchissement toute les 0,5 secondes des éléments de la page.

Je change un élement à partir de la page web, j’utilise writegroup en php. (Voir mon article : Prise en main du KNX en php ).
Et continue de lire ma BDD, sans y écrire de changement, le frontend php s’en occupe.

Il y’a 3 scripts AJAX/PHP :

  • knx-get_light_value.php : me récupère simplement les valeurs dans la BDD selon le « nom système » écrit dans le div id html.
  • knx-set_light_toggle.php : me change l’état d’une lumière, On ou Off, rien de plus sur un EIS n° 1.
  • knx-set_light_value.php : plus complexe que le précédent script, peut gérer d’autres EIS.

Evidemment, si je change l’état d’une lumière depuis un bouton poussoir, le changement est visible sur la page (ce que je fais à 0:50).

Je partagerai volontiers les sources lorsque j’aurai amélioré le schlimblik en back-end.

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

Alimentation / injecteur 5 Volts 1-wire (version beta)

Il était temps de changer la version alpha !

Même principe, même schéma électrique, sans pistolet à colle et le luxe d’un fusible :

Injecteur 5Volt pour 1-wire DIY

Injecteur 5Volt pour 1-wire DIY

Injecteur 1wire avec fusible

Injecteur 1wire avec fusible

Le boitier est vendu sur ebay.com (Cat5e Ethernet Keystone RJ-45 Jack & Surface Mount Box).

Ouf ! Il était vraiment temps de changer !

Posté dans 1-wire | 6 Commentaires

Frontend PHP pour l’écoute du bus KNX

Dans un précédent article, j’ai décris comment écouter le bus KNX pour allumer une rampe de LED via Open DMX.
En fin d’article, j’ai abordé l’aspect possible d’un frontend en PHP pour avoir une base de données MySQL à jour, en fonction des évènements du KNX.

Utilisation de groupsocketlisten pour une interface web

Utilisation de groupsocketlisten pour une interface web

L’intérêt est quasi le même que linknx, un changement sur le bus est égal à un changement en BDD sur les Groupes d’Adresses qui m’intéressent.
Le but est de pouvoir exploiter ces données sur une page web et d’autres scripts maisons sans faire de requête sur le bus, mais en interrogeant ma BDD.
Une espèce de travail en couche d’applications.

Pour rappel, je n’ai rien contre linknx, j’aurais juste du mal à adapter mon cahier des charges à cet outil, voir mon article :
Se passer de linknx et webknx2, une fausse bonne idée ?

Pour ce front-end, je me suis inspiré de mon premier script avec logtail.
En cherchant des solutions, je suis tombé sur l’extention php inotify et son tail (en commentaire).

La base

Pour commencer, toujours depuis Debian Wheezy, il faut posséder php5, php-pear ainsi qu’une base MySQL évidemment.
inotify s’installe comme ceci au plus simple :

# pecl install --force inotify

L’extention activée pour php5 pour le cli :

# echo "extension=inotify.so" > /etc/php5/cli/conf.d/inotify.ini

Selon mon premier script pour allumer ma rampe LED, re-modification de mon script d’init.d eibnetmux.
A la différence, que je log tout ce qu’il se passe sur le bus.

# Function that starts the daemon/service
#
do_start()
{
echo -n "Starting eibdnetmux"
/usr/local/bin/eibnetmux $DAEMON_ARGS
echo " done"
sleep 2
echo -n "Starting group listen"
/usr/local/bin/groupsocketlisten ip:127.0.0.1 > /tmp/knx_groupsocketlisten &
echo " done"
}

Mon fichier « log » du bus est /tmp/knx_groupsocketlisten

J’ai crée, ce qui est pour l’instant une simple table avec les Groupe Addresses qui m’intéressent, à l’éfigie de linknx :

--
-- Structure de la table `knx_ga`
--

CREATE TABLE `knx_ga` (
  `knx_ga_id` int(3) NOT NULL AUTO_INCREMENT,
  `knx_ga_groupaddress` tinytext NOT NULL,
  `knx_ga_value` text NOT NULL,
  `knx_ga_comment` text NOT NULL,
  PRIMARY KEY (`knx_ga_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

--
-- Contenu de la table `knx_ga`
--

INSERT INTO `knx_ga` (`knx_ga_id`, `knx_ga_groupaddress`, `knx_ga_value`, `knx_ga_comment`) VALUES
(1, '0/0/1', '1', 'Etat de la lumiere'),
(2, '0/0/2', '10', 'Valeur d''éclairement'),
(3, '0/0/10', '0', 'DMX');

J’ai 3 groupes d’adresses, ça n’a pas de sens sans une mise en situation.

Mise en situation

J’ai un Hager TXA213 (3 sorties variation 300W), un Hager WKT302 (poussoir 2 boutons), une lampe à la sortie 1 du TXA213.
Une simple pression sur le bouton 1 allume ma lampe, une pression continue augmente la luminosité ; une simple pression sur le bouton 2 éteind la lampe, une pression continue diminue la luminosité.

Pour le détail, voici un export de mes Groupes d’Adresses :
Groupes d’adresses pour tests (pdf)

J’ai trois groupes parmis les sept qui m’intéressent :
0/0/1 → Indication d’état.
0/0/2 → Valeur d’éclairement & Indication valeur d’éclairement.
0/0/10 → Allumage DMX.

Le script

Voici la formule magique, à dérouler, parce que c’est vraiment long.

<!--?php $file = "/tmp/knx_groupsocketlisten"; /**  * Tail a file (UNIX only!)  * Watch a file for changes using inotify and return the changed data  *  * @param string $file - filename of the file to be watched  * @param integer $pos - actual position in the file  * @return string  */ 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 😉
                    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;
            }
        }
    }
}

// Conection avec la base de données mysql
$db = mysql_connect("127.0.0.1", "root", "votremotdepassemysql");
$mysql=mysql_select_db("votrebase",$db);

$req_sel_ga     = "SELECT knx_ga_id,knx_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)) {
        $knx_ga_id              = $dat_sel_ga['knx_ga_id'];
        $knx_ga_groupaddress    = $dat_sel_ga['knx_ga_groupaddress'];
        $ga_bdd[$knx_ga_groupaddress]   = $knx_ga_id;
}

// Use it like that:
$lastpos = 0;
while (true) {
        // On tail le fichier de log
        $knxlisten = tail($file,$lastpos);
        //echo $knxlisten;
        // On réagit dès qu'on a un Write
        if (preg_match('#^Write#',$knxlisten)) {
                // Recup du Groupe d'Addresse et de la valeur qu'on converti
                preg_match('#[0-9]*\/[0-9]*\/[0-9]*#',$knxlisten,$groupaddr);
                preg_match("#[A-F0-9]*(.)$#",$knxlisten,$value);
                $value          = hexdec($value[0]);
                $groupaddr      = $groupaddr[0];
                // on regarde si ca fait parti des elements à surveiller
                if (array_key_exists($groupaddr, $ga_bdd)) {
                        // la valeur associé = l'id dans la BDD
                        $knx_ga_id_update       = $ga_bdd[$groupaddr];
                        $req_sel_ga_update      = "UPDATE knx_ga SET knx_ga_value = '$value' WHERE knx_ga_id = $knx_ga_id_update";
                        // Et on update la BDD !
                        mysql_query($req_sel_ga_update);
                        if ($knx_ga_id_update == "0/0/10" && $value == "01") exec("dmxchangecolorfader.py 255 0 255");
                        if ($knx_ga_id_update == "0/0/10" && $value == "00") exec("dmxchangecolor.py 0 0 0");
                }
        }
}

Abracadabra !
C’est posté sans mise au propre, mon dernier partage de script PHP était pour le 1-wire, il a fallu faire une archive pour un script plus simple, le voici brut, à personnaliser, poser des includes, variables de configuration, etc…

En gros, il fait quoi ce script ?

Il récupère les groupes d’adresses à surveiller dans la BDD.
Il fait un tail sur notre fichier de sortie groupsocketlisten.
Pour chaque nouvel évènement « Write », il regarde si le groupe d’adresse fait parti de ceux dans la BDD.
Si c’est le cas, il y écrit la valeur.

Cas pratique :

Si j’allume ma lumière, 0/0/1 passe à 1 sur mon bus.
groupsocketlisten l’écris dans le fichier /tmp/knx_groupsocketlisten
Ce script voit passer 0/0/1, il sait que sa valeur m’intéresse, il y écrit immédiatement la valeur dans la base de donnée.

Il suffit de lancer ce script par le cron, à la main (en ligne de commande uniquement), par un init.d ou autre.

La mise à jour de la base est quasi instantanée !
Le fonctionnement du script ci-dessous charge les GA de la base MySQL et les place dans une variable puis les compare à GA qui circule sur le bus.

A la fin du script, la partie liée à 0/0/10 est pour reprendre le fonctionnement de l’article de base et l’allumage du DMX.
Je songe à  l’intégrer différemment, très certainement par l’ajout d’un champ contenant la spécificité et le script à exécuter.

Résultat du script via phpmyadmin

Résultat du script via phpmyadmin

Et voila ! Ou comment re-inventer la roue : linknx !

Il me reste à personnaliser ce script via des includes, des paramètres, rajouter un champs dans la table pour appeler un GA par un nom, un autre champs IES pour le write, et faire des essais sur une page web.

Posté dans Debian, php, Sysadmin, Web | 1 Commentaire

Communication entre le bus KNX et un serveur Linux

Jusqu’à présent, j’ai découvert comment envoyer des ordres ou obtenir une valeur avec mon bus KNX.
Que ce soit en PHP ou par ligne de commande.

Mon souhait est de pouvoir faire l’inverse : depuis le bus KNX, de donner un autre à mon serveur.
Plusieurs applications possibles, en voici deux concrètes :

  • Allumer/couper les lumières d’ambiance DMX, changer les couleurs.
  • Allumer/couper le wifi.

C’est sans limite en fait.
Du moment où j’envois une commande (boutton poussoir) au serveur celui-ci peut être interprété comme bon me semble.
Je passe de l’électrique de puissance à l’informatique classique.

Comment ça marche ?

J’ai essayé de faire un schéma :

Schéma de principe de l'écoute du bus  KNX

Schéma de principe de l'écoute du bus KNX

Coté programmation, j’ai crée un groupe d’adresses 0/0/10 qui ne contient aucune action, le groupe est lié à l’interrupteur bouton poussoir.

Configuration ETS4 avec un groupe vite pour le DMX

Configuration ETS4 avec un groupe vite pour le DMX

Notre serveur, équipé d’eibnetmux (lien vers son installation) utilise grouplisten pour écouter ce qu’il se passe sur le bus KNX pour un Groupe d’Adresse spécifié, ici le GA 0/0/10.

La fonction grouplisten est exécutée en même temps que le démarrage d’eibnetmux, j’ai rajouté quelques lignes à partir de mon script initial.
La sortie de cette commande est redirigée vers un fichier.

#
# Function that starts the daemon/service
#
do_start()
{
echo -n "Starting eibdnetmux"
/usr/local/bin/eibnetmux $DAEMON_ARGS
echo " done"
sleep 2
echo -n "Starting group listen"
/usr/local/bin/grouplisten ip:127.0.0.1 0/0/10 > /tmp/knx_0-0-10 &
echo " done"
}

Je vais me servir de ce fichier pour surveiller les changements d’état.
J’utilise l’outil logtail pour vérifier les nouveaux évènements.

Pour cet exemple, je souhaite que l’utilisation du bouton poussoir allume mon bandeau RGB, dont j’ai récemment effectué l’installation.

# touch /usr/local/bin/knx2dmx
# chmod +x /usr/local/bin/knx2dmx
# vi /usr/local/bin/knx2dmx
#!/bin/bash

lockfile=/tmp/knx2dmx.run
if [[ -f $lockfile ]] ; then
    echo "knx2dmx déjà en cours d'exécution ou supprimer le fichier $lockfile"
    exit
fi
touch $lockfile

groupaddress=$1
file=/tmp/knx_$groupaddress

bouclette="yes"
# Boucle sans fin
while [ $bouclette = "yes" ]
 do
 {
  # Mais on est pas à 1 seconde près
  sleep 1
   value=`/usr/sbin/logtail -f -o $file | grep "Write" | cut -d" " -f4`
  if [ "$value" == 01 ]
  then
        # Ici j'allume mon bandeau RGB, mais toute autre action est envisageable
        /usr/local/bin/dmxchangecolorfader.py 255 25 100
  elif [ "$value" == 00 ]
  then
        # Je l'éteinds
        /usr/local/bin/dmxchangecolor.py 0 0 0
 fi
 }
done

Et celui là, je le lance dans le cron.

*/10 *          * * *   root    /usr/local/bin/knx2dmx 0-0-10

Donc si mon script, via logtail, détecte que l’adresse de groupe 0/0/10 KNX passe à 1, il allume le strip RGB DMX.
A l’inverse, s’il détecte un 0, il l’éteint.

A titre de supplément, le script dmxchangecolor.py est celui abordé dans l’installation d’OLA.

#!/usr/bin/python
import sys, array
from ola.ClientWrapper import ClientWrapper

def DmxSent(state):
  wrapper.Stop()

universe = 1
data = array.array('B')
data.append(int(sys.argv[1]))
data.append(int(sys.argv[2]))
data.append(int(sys.argv[3]))
wrapper = ClientWrapper()
client = wrapper.Client()
client.SendDmx(universe, data, DmxSent)
wrapper.Run()

Et le script dmxchangecolorfader.py provient aussi de la page wiki d’OLA.
Que j’ai beaucoup bidouillé car je ne sais pas codé en python :
Je n’en suis pas fier, surtout qu’il ne faut pas mettre de valeur à 0.

#!/usr/bin/python
import sys, array
from ola.ClientWrapper import ClientWrapper

red_arg = int(sys.argv[1])
green_arg = int(sys.argv[2])
blue_arg = int(sys.argv[3])

red = 0
green = 0
blue = 0

wrapper = None
loop_count = 0
TICK_INTERVAL = 10  # in ms

def DmxSent(state):
  if not state.Succeeded():
    wrapper.Stop()

def SendDMXFrame():
  # schdule a function call in 100ms
  # we do this first in case the frame computation takes a long time.
  wrapper.AddEvent(TICK_INTERVAL, SendDMXFrame)

  # compute frame here
  data = array.array('B')
  global loop_count
  global red
  global green
  global blue

  if red == (red_arg-1):
    data.append(red_arg)
  else:
    red = loop_count % red_arg
    data.append(red)

  if green == (green_arg-1):
    data.append(green_arg)
  else:
    green = loop_count % green_arg
    data.append(green)

  if blue == (blue_arg-1):
    data.append(blue_arg)
  else:
    blue = loop_count % blue_arg
    data.append(blue)

  loop_count += 1

  if (red == (red_arg-1)) and (green == (green_arg-1)) and (blue == (blue_arg-1)):
    exit()

  # send
  wrapper.Client().SendDmx(1, data, DmxSent)

wrapper = ClientWrapper()
wrapper.AddEvent(TICK_INTERVAL, SendDMXFrame)
wrapper.Run()

Résultat

Pour aller plus loin avec un frontend php

Et voila ! Une bonne base pour faire interagir le serveur depuis le bus KNX.
Je pourrai rajouter autant de grouplisten que necessaire, mais dans une certaine mesure, il sera certainement préférable d’écouter tout ce qu’il se passe sur le bus via groupsocketlisten.

Avec un principe un petit peu différent :

Utilisation de groupsocketlisten pour une interface web

Utilisation de groupsocketlisten pour une interface web

Dans ce cas, groupsocketlisten écoute tout ce qu’il se passe sur le bus.
Un script PHP est à l’écoute des informations, certainement sur le même principe du logtail.
Il filtre et remplit des informations dans la base de données MySQL.

Cette partie là est intéressante, si par exemple, j’allume une lumière derrière un variateur TXA213, groupsocketlisten y voit défiler deux informations :

Write from 0.2.189 to 0/0/1: 01
Write from 1.1.2 to 0/0/7: 01
Write from 1.1.2 to 0/0/8: AF

Ici, j’ai allumé ma lumière grâce à un « groupswrite ip:127.0.0.1 0/0/1 1 », je le vois sur mon bus (0.2.189).
Et deux autres informations utiles y circulent :
– 0/0/7 correspond à l’indicateur d’état, à 01 donc ma lampe est allumée.
– 0/0/8 correspond à l’indicateur de la valeure d’éclairement en hexadécimale sur FF (255).
Ici la valeur hexa AF (FF étant le max) correspond à 175 en décimale (255 étant le max).
Ainsi, avec un base de données bien pensée, il est possible de faire un filtre intelligent : un type d’objet c’est tant et tant d’information à récolter avec tels et tels groupes d’adresses.
On peut pousser le bouchon plus loin, c’est ce « frontend » PHP qui pourrait exécuter des actions sur le système tel que l’allumage DMX.

Une fois la BDD avec des informations actualisées, il ne reste plus qu’à les exploiter à travers une page web.

Une solution qui me semble bonne pour les fondations d’une bonne usine à gaz.
Je vais commencer quelque chose dans ce principe pour un prochain article.

Posté dans Debian, dmx, KNX, led, Sysadmin | 1 Commentaire

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

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

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

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

Structure de la base

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

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

Une seconde table avec les valeurs, son squelette :

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

Le script automatique

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

Ce qui donne cet ensemble :

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

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

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

?>

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

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

Le contenu de la base

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

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

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

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

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

Sonde 1-wire dans la base MySQL via phpmyadmin

Sonde 1-wire dans la base MySQL via phpmyadmin

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

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

Execution

On peut faire un simple test :

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

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

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

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

Redemarrez owserver et refaite le test.

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

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

Au bout de quelques heures :

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

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

Télécharger

Télécharger l’archive

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

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

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

Se passer de linknx et webknx2, une fausse bonne idée ?

Aujourd’hui, grande réflexion autour de linknx et knxweb2.
Je me suis attardé sur ces deux outils, en plus de leur découverte via une Live CD.

Les VM, rien de plus pratique pour essayer sans casser

Les VM, rien de plus pratique pour essayer sans casser

Le but étant, entre autres, de découvrir l’interface de knxweb2 (knxweb v1 sur le LiveCD), et comprendre la communication entre le click et l’ampoule.

KnxWeb2

C’est à peu près démystifié : knxweb2 tourne en AJAX/jQuery qui communique en XML à travers un savant mélange avec linknx.
C’est puissant ! Instantané.

Test de KNXWEB2

Test de KNXWEB2

Seul bémol, au jour d’aujourd’hui, je ne me vois pas capable de « maîtriser » linknx et knxweb2, car là dedans, je n’ai pas mes lots :
– Asterisk
– Notifry
– DMX
– 1-wire
– Alarme
– Teleinfo
– ZoneMinder (vidéo surveillance).

C’est très certainement insérable dans knxweb2, mais le temps que je prenne pour intégrer l’ensemble de mon cahier des charges, j’ai mieux fait de partir de zéro.
Je souhaite connaître au maximum le cheminement de mon usine à gaz pour l’adapter et la faire évoluer au grès des besoins.

Mon problème, c’est que jamais je n’arriverai à égaler la réactivité de knxweb2, mais je vais essayer de m’en approcher.

Linknx

J’ai continué l’approche sur linknx avec une page de test php, et les actions en rapports.
Ça permet de bien saisir la communication :
Clic → PHP → linknx → eibnetmux → knx → ampoule.
Mais au final, d’après ce script de test en php, ça revient à la même chose que :
Clic → PHP → Class PHP Eibnetmux → eibnetmux → knx → ampoule.

Pour linknx, la base utilise un fichier le config xml du paquet.
Pour PHP @ eibnetmux, la base utilise une base de données MySQL et des scripts.

C’est kif kif.
Entre la Class PHP KNX et l’utilisation de linknx par PHP, le fonctionnement est semblable : il y’a ouverture d’un socket pour lire et écrire les informations à la couche inférieure.

Donc pour la partie PHP → KNX, avec ou sans linknx, je ne m’évite pas du travail, ne me complique pas plus la tâche.

Pour conclure

Beaucoup de doutes et de questions.
Au jour d’aujourd’hui, je pense remplacer linknx par des scripts PHP et une base MySQL.
Ainsi que knxweb2 par une interface web perso, en sachant que je n’arriverai pas à égaler sa réactivité, mais je gagnerai en maîtrise, souplesse vis à vis de mon cahier des charges.

Posté dans Debian, KNX, php, Sysadmin | 5 Commentaires

Interroger les sondes 1-wire par un script PHP

Page PHP de requêtes 1-wire

Un point que je n’avais pour l’instant pas abordé dans mes différents articles sur le 1-wire :

Je n’ai pas abordé le contrôle du 1-wire en PHP.

Pour faire quoi ?

Une grosse usine à gaz !
Utiliser PHP pour interroger les sondes 1-wire, c’est tout simplement ce qu’il y’a de plus logique dans mon projet, vue que je souhaite une interface à la knxweb2 mais home made.
L’affichage d’une température sur un plan et toute autre utilisation des mesures se fera par PHP.

Quels paquets php à installer ?

Comme vu dans la phase de découverte, owserver est désormais disponible en package compilé pour Debian Wheezy.
Pour les librairies PHP, il existe deux paquets aux noms semblables : libow-php5 et libownet-php.

Quelle différence ? La question a été posée au contributeur du package, voici sa réponse :
libownet-php ne peut que communiquer avec owserver, qui, lui-même pourra communiquer avec d’autres owserver et/ou matériel 1-wire.
libow-php5 est un wrapper autour de la bibliothèque C qui permet de communiquer directement avec le matériel 1-wire.

Alors on installe libownet-php.

# apt-get install libownet-php

Ce qui a pour effet d’installer un fichier php de class au chemin suivant :
/usr/share/php/OWNet/ownet.php

Une page d’exemple est disponible au chemin suivant :
/usr/share/doc/libownet-php/examples/ownet_example.php

Cet exemple fait référence à un fichier bcadd.php, il s’agit d’un hack car certaines versions distribuées de php ne permettent pas l’utilisation de cette fonction, fournir cette fonction par un include permet de contourner le problème. Evidemment, sous Debian Wheezy hébergement maison, ce qu’il y’a de plus classique, pas de problème avec bcadd, donc le « require » ne sera pas utilisé.

Récupérer des valeurs en PHP

Pour ce test, j’ai placé sur mon bus 1-wire :

  • 1x DS18B20 : sonde de température à l’extérieur.
  • 1x DS18B20+PAR : sonde de température à l’intérieur.
  • 1x DS2406 : capteur d’ouverture de fenêtre.
  • 1x DS2401 : capteur d’ouverture de fenêtre.

L’ensemble des fonctions ownet php sont visibles sur la page du projet :
http://owfs.org/index.php?page=ownet-php

Je récupère le fichier ownet.php, sans quoi on obtient forcément l’erreur suivante :

PHP Fatal error:  Class 'OWNet' not found
# cp /usr/share/php/OWNet/ownet.php /var/www/1-wire/

Et mon index.php

<?php
require "ownet.php";

$ow=new OWNet("tcp://127.0.0.1:4304");

?>
Temp&eacute;rature ext&eacute;rieure :
<?
$temp_ext = $ow->read("/28.EA54B5030000/temperature");
// Décommenter la ligne suivante pour avoir les détails du composant
//var_dump($ow->dir("/28.EA54B5030000",OWNET_MSG_READ,true));
echo $temp_ext;
// ------------------
?>

<br />
Temp&eacute;rature int&eacute;rieure :
<?php
$temp_int = $ow->get("/28.919277030000/temperature",OWNET_MSG_READ,false);
// Décommenter la ligne suivante pour avoir toutes les infos sur la température
//var_dump($ow->get("/28.919277030000/temperature",OWNET_MSG_READ,true));
echo $temp_int;
// ------------------
?>

<br />
Fen&ecirc;tre DS2406 :
<?php
$fenetre_ds2406 = $ow->read("/12.D0457D000000/sensed.A");
// Décommenter la ligne suivant pour avoir toutes les infos sur le PIO A
//var_dump($ow->get("/12.D0457D000000/sensed.A",OWNET_MSG_READ,true));
echo ($fenetre_ds2406)?"ouverte":"ferm&eacute;e";
// ------------------
?>

<br />
Fen&ecirc;tre DS2401 :
<?php
$fenetre_ds2406 = $ow->presence("/01.DC4343140000");
// Décommencer la ligne suivante pour avoir les détails, minimaliste car c'est une présence
//var_dump($ow->dir("/01.DC4343140000",OWNET_MSG_READ,true));
echo ($fenetre_ds2406)?"ferm&eacute;e":"ouverte";
// ------------------
?>

<br />
Page PHP de requêtes 1-wire

Page PHP de requêtes 1-wire

J’ai laissé les lignes var_dump commentées, elles peuvent servir de débogage.
Le port 4304 à adapter selon votre serveur owserver ( /etc/owfs.conf ).

A noter, comme vue dans mon article sur le DS2406, sensed.A retourne un 1 lorsque l’ILS est ouvert, 0 lorsque qu’un aimant est à proximité, ce qui pourrait porter à confusion.

Read et Get sont sur un bateau

Les read et le get, syntaxé comme ceci, apportent le même résultat.

$ow->get("/28.919277030000/temperature",OWNET_MSG_READ,false);
$ow->read("/28.919277030000/temperature");

D’après la doc de owfs.org le get parcourt chaque valeur de l’élément désiré et y applique une fonction/constante.
Tandis que le read, récupère la valeur demandée, point final.

Dans mes tests, et pour une requête de température il s’avère que le get ne retourne pas toujours de valeurs.
Il semble fonctionner à un niveau plus « bas » que le read.
Donc la fonction read est à privilégier.

Et maintenant ?

L’insertion des données dans une base MySQL, pour un prochain article.

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

Configuration d’une platine de tests KNX avec ETS

ETS, le Saint Graal du KNX ! Un prix exorbitant pour le simple particulier.
Heureusement, l’association KNX s’adapte.

ETS 4 ?

KNX ETS4 eCampus est un super moyen d’apprendre le principe de programmation du KNX via ETS4.
C’est de l’e-formation bien faite.
Ça semble fastidieux, surtout lorsque les vidéos sont en anglais, la simulation en allemand et les questions en français (ça fait travailler les langues)
Tâchez d’obtenir votre diplôme avec  un niveau d’apprentissage de 85 %.

KNX eCampus

KNX eCampus

La récompense ? Une licence ETS4 Lite, cette licence permet de gérer un projet de 20 éléments KNX.
Suffisant pour savoir si KNX est fait pour vous et si vous êtes fait pour KNX.

Direction l’eCampus pour tout savoir sur ETS  et le KNX : http://wbt4.knx.org/
(j’espère obtenir une licence Pro avec la pub que je leur fait !)

Le seul souci est lié à l’utilisation eibnetmux, vu qu’il ne fonctionne qu’avec ETS3.

Quoi qu’il en soit, l’ETS4 eCampus permet de se familiariser avec ETS et le jour venu d’acquérir une licence.
Je n’ai pas le besoin de rédiger un article sur comment programmer une platine avec ETS4, ce genre de support reprend très bien le b-a ba de la programmation.

Commande groupée ?

Sur certains forums, sont régulièrement organisées des commandes groupées de licence ETS, ce qui permet d’obtenir pas loin de 50% de réduction.
Il faut rester à l’affût et saisir les bonnes occasions.

ETS 3 ?

Il est possible d’obtenir une licence ETS3 par l’intermédiaire d’un autre passionné de domotique, ou si vous êtes suffisamment proche de votre électricien.
Le logiciel est plus ancien, il est théoriquement plus facile d’en trouver.

De temps en temps, on retrouve des ventes eBay pour une license ETS3, de ce style :

eBay licence KNX ETS3 Pro

eBay licence KNX ETS3 Pro

Une opportunité à saisir.

Concernant la programmation avec ETS3, en ayant suivi les cours de l’eCampus ETS4, on s’en sort avec le 3.

Autrement, il existe un très bon dictatiel disponible sur le forum electrotechnique-fr.com.

Posté dans ETS3, ETS4, KNX | Laisser un commentaire

Installation d’OLA et prise en main du DMX à travers python & php

Maintenant que notre contrôleur compatible Open DMX, nous allons pouvoir l’exploiter logicielement.
Mon but étant de pouvoir changer la couleur (ce qui reviens à allumer/éteindre) en quelques clics ; ainsi que de voir ce qu’il est possible de faire en ligne de commande et idéalement de changer la couleur depuis une page web.

La platine de test DMX

Mon installation est composée de :

  • DMX USB PC V3 (Contrôleur USB / DMX) → 36,50 €.
  • Câble XLR de récup → 0 €.
  • Décodeur DMX RGB → 23,08 €.
  • Alim 12V de récup → 0 €.
  • Câble pour connecter les bandeaux RGB → 1,50 €.
  • 2x Bandeau RGB 12V 5050 30cm → 1,35 € / pièce.
  • Bouchon DMX , livré avec le DMX USB PC → 0 €.

Soit  environ 67 € le tout, frais de ports inclus.

Platine de tests DMX

Platine de tests DMX

Un petit schéma de principe :

Schéma de principe de la phase de tests

Schéma de principe de la phase de tests

En phase final, je compte remplacer le XLR par de l’Ethernet et le strip RGB par des spots encastrables LED RGB de ce style :

Spot encastrable LED RGB 10mm

Spot encastrable LED RGB 10mm

Le revendeur est l’ancien Eurolite.de, devenu Steinigke Showtechnic : la fiche produit du spot encastable LED RGB 10mm.

Installation de Open Lighting Architecture (OLA)

Toujours depuis une Debian Wheezy, on commence par installer différents paquets qui seront nécessaire pour la compilation.

# apt-get install flex libmicrohttpd5 bison libprotobuf-dev protobuf-compiler uuid uuid-dev libcppunit-dev python python-protobuf build-essential
# ldconfig

Et on récupère l’archive d’OLA.

# cd /usr/src/
# wget http://linux-lighting.googlecode.com/files/ola-0.8.18.tar.gz
# tar zxvf ola-0.8.18.tar.gz
# cd ola-0.8.18
# ./configure --enable-python-libs --enable-http

Le « enable-python-libs » permettra d’envoyer des commandes DMX à partir d’un script python.
Le « enable-http » permettra d’utiliser de tester ola à travers une page http.

# make
# make install
# ldconfig

Et voila ! C’est installé.
Ola exige d’être démarré avec un utilisateur non root.

# adduser --disabled-password ola
# su ola

Avant cette première exécution, il est important de veiller à ce que le contrôleur USB/DMX soit reconnu en tant que /dev/dmx0.

# olad -l 3

Le 3 (/4) correspond au niveau de verbosity.

Vous devriez voir au moins ces lignes apparaîtrent :

PluginManager.cpp:74: Trying to start Enttec Open DMX
DeviceManager.cpp:111: Installed device: OpenDmx USB Device:6-0
PluginManager.cpp:78: Started Enttec Open DMX

Si vous avez installez libmicrohttpd5, vous devriez pouvoir accéder à la page http://ip_du_serveur_ola:9090 .
Et configurer votre fixture aka « universe« .

Page de configuration des univers

Page de configuration des univers

J’ai attribué au contrôleur RGB l’adressage DMX 1.
Dont la notice a été scannée.

adressage DMX du contrôleur RGB

adressage DMX du contrôleur RGB

Dans l’onglet Console, je peux modifier la valeur de mes trois canaux RGB et donc chacune des trois couleurs.

Console ola pour contrôleur RGB

Console ola pour contrôleur RGB

Ce qui donne :

Rendu instantané entre OLA et le strip RGB

Rendu instantané entre OLA et le strip RGB

Youpi !
De quoi être tranquille au démarrage de la machine, j’ai pondu ce petit init.d script pour ola à partir du skeleton.

# vi /etc/init.d/olad
#! /bin/sh
### BEGIN INIT INFO
# Provides:          olad
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: olad initscript
# Description:       Open Lighting Architecture init script
### END INIT INFO

# Author: Lionel / domolio.fr
#

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin/
DESC="Open Lighting Architecture Daemon"
NAME=olad
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="-f"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
USER=olad

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

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

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --chuid $USER --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --chuid $USER --quiet --pidfile $PIDFILE --exec $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
        # Add code here, if necessary, that waits for the process to be ready
        # to handle requests from services started subsequently which depend
        # on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --chuid $USER --stop --quiet --retry=TERM/10/KILL/5 --pidfile $PIDFILE --name $NAME
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        # Wait for children to finish too if this is a daemon that forks
        # and if the daemon is only ever run from this initscript.
        # If the above conditions are not satisfied then add some other code
        # that waits for the process to drop all resources that could be
        # needed by services started subsequently.  A last resort is to
        # sleep for some time.
        start-stop-daemon --chuid $USER --stop --quiet --oknodo --retry=0/10/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        # Many daemons don't delete their pidfiles when they exit.
        rm -f $PIDFILE
        return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
        #
        # If the daemon can reload its configuration without
        # restarting (for example, when it is sent a SIGHUP),
        # then implement that here.
        #
        start-stop-daemon --chuid $USER --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
        return 0
}

case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  status)
        status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
        ;;
  #reload|force-reload)
        #
        # If do_reload() is not implemented then leave this commented out
        # and leave 'force-reload' as an alias for 'restart'.
        #
        #log_daemon_msg "Reloading $DESC" "$NAME"
        #do_reload
        #log_end_msg $?
        #;;
  restart|force-reload)
        #
        # If the "reload" option is implemented then remove the
        # 'force-reload' alias
        #
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
        exit 3
        ;;
esac

:
# chmod +x /etc/init.d/olad
# insserv olad

Ainsi Open Lighting Architecture sera lancé à chaque démarrage.

Conclusion d’OLA

Cool, ça prend forme !
Il manque un gros détail : ça ne me semble pas viable de contrôler les couleurs à travers l’interface d’administration d’OLA, j’ai besoin de le faire en dehors de cette interface.
D’où l’intérêt d’avoir installé les libraires python d’Open Lighting Architecture.

Prise de contrôle du DMX par PHP & Python

Mon idée est de pouvoir disposer d’une roue chromatique depuis mon smartphone et pouvoir changer les couleurs de mon escalier, par exemple, pour la frime par challenge.
OLA a été installé avec des librairies python, servons-nous en.
Le wiki d’OLA fait part de scripts simple en pyhton.

# vi testcolor.py
import array
from ola.ClientWrapper import ClientWrapper

def DmxSent(state):
  wrapper.Stop()

universe = 1
data = array.array('B')
data.append(10)
data.append(50)
data.append(255)
wrapper = ClientWrapper()
client = wrapper.Client()
client.SendDmx(universe, data, DmxSent)
wrapper.Run()

En ayant olad d’exécuté, on lance :

# python testcolor.py

Si le script ne vous retourne rien et vous éclaire d’un joli bleu, tant mieux !

A l’inverse, si le script python retourne ceci :

Traceback (most recent call last):
  File "testor.py", line 2, in 
    from ola.ClientWrapper import ClientWrapper
ImportError: No module named ola.ClientWrapper

C’est que libraires d’OLA ne sont pas importables par le script.
L’une des solutions consiste à copier les libraires dans le script de travail de python.

# cp -r /usr/local/lib/python2.7/site-packages/ola /usr/lib/python2.7/

Relancez le script et la vie est bleue !
Voila pour la partie pyhton -> DMX.

Color Picker pour DMX

Color Picker pour DMX


Place maintenant à la partie PHP Python.
Dans mon délire d’avoir une roue chromatique ou quelque chose qui y ressemble, j’ai utilisé un script jQuery.

J’ai modifié le script pyhton pour lui passer les couleurs RGB en argument :

#!/usr/bin/python
import sys, array
from ola.ClientWrapper import ClientWrapper

def DmxSent(state):
  wrapper.Stop()

universe = 1
data = array.array('B')
data.append(int(sys.argv[1]))
data.append(int(sys.argv[2]))
data.append(int(sys.argv[3]))
wrapper = ClientWrapper()
client = wrapper.Client()
client.SendDmx(universe, data, DmxSent)
wrapper.Run()

Script nommé dmxchangecolor.py placé dans /usr/local/bin/ avec droit en éxecution.

Ma page php :

<?php
function html2rgb($color) {
    if ($color[0] == '#')
        $color = substr($color, 1);
    if (strlen($color) == 6)
        list($r, $g, $b) = array($color[0].$color[1],
                                 $color[2].$color[3],
                                 $color[4].$color[5]);
    elseif (strlen($color) == 3)
        list($r, $g, $b) = array($color[0].$color[0], $color[1].$color[1], $color[2].$color[2]);
    else
        return false;
    $r = hexdec($r); $g = hexdec($g); $b = hexdec($b);
    return array($r, $g, $b);
}

if(isset($_POST['envoyer'])) {
        $htmlcolor = $_POST['htmlcolor'];
        $rgb = html2rgb($htmlcolor);
        exec("dmxchangecolor.py $rgb[0] $rgb[1] $rgb[2]");
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <link rel="stylesheet" href="css/colorpicker.css" type="text/css" />
    <link rel="stylesheet" media="screen" type="text/css" href="css/layout.css" />
    <title>ColorPicker DMX - jQuery plugin</title>
    <script type="text/javascript" src="js/jquery.js"></script>
    <script type="text/javascript" src="js/colorpicker.js"></script>
    <script type="text/javascript" src="js/eye.js"></script>
    <script type="text/javascript" src="js/utils.js"></script>
    <script type="text/javascript" src="js/layout.js?ver=1.0.2"></script>
</head>
<body>
<form action="" method="post" >
        <input type="text" maxlength="6" size="6" id="colorpickerField" name="htmlcolor" value="<?php echo $htmlcolor ?>" /><br />
        <input type="submit" value="Envoyer" name="envoyer" />
</form>
</body>
</html>

Simple et efficace, je choisis ma couleur, valide le formulaire, la fonction php convertit la couleur HTML en RGB qui la soumet au script python.

Télécharger le script PHP/jQuery/DMX.

Et voila ! J’aurais préféré une libraire PHP comme pour le KNX et le 1-wire, mais je n’en ai pas trouvé malheureusement.
Passer les couleurs à un script python lui même appelé commande php, ça fera l’affaire pour ma future machine à gaz.

Php Show Controller

Autrement, j’ai découvert Php Show Controller (PSC) et son sympathique créateur Laurent.
https://github.com/RenZ0/php-show-controller

L’outil est très intéressant si l’on souhaite scénariser ses lumières.
Le principe est résumé dans le README :

With php interface you change sql data.
Python engine reads sql data, and send it to OLA.
OLA use your hardware to send DMX signal.

Le paquet a un petit défaut, il n’est pas encore compatible PHP 5.4 car il exige les register_globals (qui ont disparus depuis php 5.4)
Mais d’après l’auteur, les modifications sont pour très bientôt, pour les impatients, en modifiant les quelques GET et POST vous pourrez vite vous faire une idée de la puissance de PSC.

Voici comment l’installer :
Il faut dans un premier temps python-mysqldb et bien sûr un serveur MySQL.

# apt-get install python-mysqldb mysql-server
# wget "http://www.imaginux.com/ccount/click.php?id=148" -O php-show-controller_1.1.1.tar.gz
# tar zxvf php-show-controller_1.1.1.tar.gz
# cd php-show-controller

On crée une base nommée psc.

mysql -p
create database psc;
quit;

On importe la structure et les paramètres de base :

# gzip -d sql/psc_base.sql.gz
# mysql -p psc < sql/psc_base.sql

Puis on copie les fichiers web pour apache2

# cp -r psc/ /var/www/
# cd /var/www/
# chown -R www-data:www-data psc

On modifie le fichier des paramètres MySQL pour que PHP s’en serve :

# vi psc/config.php

Et les paramètres MySQL pour que pyton utilise également MySQL :

# cd /usr/src/php-show-controller/engine/
# vi config.py

Et rendez-vous sur la page web de votre installation pour découvrir PSC.
N’oubliez pas de vous aider de README pour le paramétrage de votre scénario.

Conclusion

Après avoir installé les drivers Open DMX USB, après avoir installé Open Lighting Architecture et ses libraires, après avoir testé un scripts python et php.
Je suis sûr et certain de pouvoir introduire des lumières d’ambiances dans mon projet domotique.
Escalier, pièces à vivre, informations lumineuses, les idées sont nombreuses, mais je sais que je pourrais le faire et introduire les interactions dans mon usine à gaz par l’intermédiaire de pages php.

Posté dans Debian, dmx, led, Open DMX | 9 Commentaires