Dans cet article, je vous propose une méthode pour récupérer l’état des détecteurs sans fil de son alarme Visonic avec un RFXCOM en XPL-Perl sous Linux.

Quel intérêt ?

A la maison, les volets se ferment automatiquement au coucher du soleil. En cette période d’été il fait bon de rester sur la terrasse le soir. Seulement, si pendant ce temps les volets se ferment, on risque de rester bloqué à l’extérieur. Jusqu’à présent on prenait soin de ne pas oublier son téléphone (pour les rouvrir) ou les clés de la porte d’entrée.
Partant du constat que chaque porte est équipée d’un détecteur d’ouverture Visonic et que je dispose d’une interface RFXCOM branchée au serveur, pourquoi ne pas récupérer l’état de ces capteurs et mettre la condition suivante : « Si la porte de la terrasse est ouverte, ne pas fermer le volet ».

Voilà à quoi ressemble un détecteur d’ouverture Visonic :

Détecteur d'ouverture sans-fil Visonic


Ce capteur coûte un peu moins de 50€ et peut être utilisé pour cette fonction sans forcément avoir une centrale d’alarme Visonic.

Les messages XPL

Une fois la pile insérée, lancez un xpl-logger pour voir les messages de votre détecteur.
Vous devriez obtenir quelque chose comme ceci :

192.168.10.14:45080 [xpl-trig/security.zone: bnz-rfxcomrx.serveurxpl -> * - alert/powercode.bba0e9 state=true]
192.168.10.14:45080 [xpl-trig/x10.security: bnz-rfxcomrx.serveurxpl -> * - alert bba0e9 powercode]
192.168.10.14:45080 [xpl-trig/security.zone: bnz-rfxcomrx.serveurxpl -> * - alert/powercode.bba0e9 state=true]
192.168.10.14:45080 [xpl-trig/x10.security: bnz-rfxcomrx.serveurxpl -> * - alert bba0e9 powercode]
192.168.10.14:45080 [xpl-trig/security.zone: bnz-rfxcomrx.serveurxpl -> * - alert/powercode.bba0e9 state=true]
192.168.10.14:45080 [xpl-trig/x10.security: bnz-rfxcomrx.serveurxpl -> * - alert bba0e9 powercode]
192.168.10.14:45080 [xpl-trig/security.zone: bnz-rfxcomrx.serveurxpl -> * - alert/powercode.bba0e9 state=false]
192.168.10.14:45080 [xpl-trig/x10.security: bnz-rfxcomrx.serveurxpl -> * - normal bba0e9 powercode]
192.168.10.14:45080 [xpl-trig/security.zone: bnz-rfxcomrx.serveurxpl -> * - alert/powercode.bba0e9 state=false]
192.168.10.14:45080 [xpl-trig/x10.security: bnz-rfxcomrx.serveurxpl -> * - normal bba0e9 powercode]
192.168.10.14:45080 [xpl-trig/security.zone: bnz-rfxcomrx.serveurxpl -> * - alert/powercode.bba0e9 state=false]
192.168.10.14:45080 [xpl-trig/x10.security: bnz-rfxcomrx.serveurxpl -> * - normal bba0e9 powercode]

Dans cet exemple, j’ai ouvert (state=true) puis fermé la porte (state=false).
Chose intéressante, les capteurs émettent à chaque action le message trois fois de suite. Il n’y a pas d’acquittement, c’est donc une sécurité dans le cas où une transmission aurait été perturbée.

Le script Perl

L’objectif est maintenant d’écrire un script Perl pour qu’il écoute tous les messages XPL, filtre celui du détecteur, ignore les trois répétitions identiques, analyse l’état (ouvert ou fermé) et exécute une action. De plus, le capteur renvoie périodiquement son état, il faudra l’ignorer si celui-ci est le même que le précédent reçu.
Dans mon cas, l’action est d’informer HomeSeer (qui gère les volets roulant) de l’état du capteur (et donc de la porte) et en fonction, fermera ou non le volet.

#!/usr/bin/perl -w
 
# $Id$
 
=head1 NAME
 
xpl-porte - Perl script pour détecter si la porte de la salle à manger et ouverte ou fermée et renvoi l'état à HomeSeer
Code from http://clement.storck.me
 
=head1 SYNOPSIS
 
  xpl-porte [flags] [options] [filter...]
  where valid flags are:
    -h - show this help text
    -head - dump the head of all xPL messages
    -body - dump the body of all xPL messages
    -v - verbose client mode
  and valid options are (default shown in brackets):
    -i if0 - the interface for xPL messages (first non-loopback or loopback)
  Any filter arguments are concatenated with space and passed to the
  xPL callback setup.
 
  # start the logger listening and broadcasting on first ethernet
  # interface in verbose mode
  xpl-porte -i eth0 -v
 
  # start but only log "x10.*" messages
  xpl-porte -i eth0 -v class=x10
 
=cut
 
use strict;
use warnings;
use Getopt::Long;
use Pod::Usage;
use xPL::Client;
use Switch;
 
 
$|=1; # autoflush helps debugging
 
my %args = ( vendor_id => 'bnz', device_id => 'listener', );
my %opt = ();
my $verbose;
my $interface;
my $help;
my $man;
my $verbose_head;
my $verbose_body;
GetOptions('verbose+' => \$verbose,
           'interface=s' => \$interface,
           'define=s' => \%opt,
           'help|?|h' => \$help,
           'man' => \$man,
           'head' => \$verbose_head,
           'body' => \$verbose_body,
           ) or pod2usage(2);
pod2usage(1) if ($help);
pod2usage(-exitstatus => 0, -verbose => 2) if ($man);
 
$args{'interface'} = $interface if ($interface);
$args{'verbose'} = $verbose if ($verbose);
 
# Create an xPL Client object
my $xpl = xPL::Client->new(%args, %opt) or die "Failed to create xPL::Client\n";
 
# Add a callback to receive all incoming xPL messages
$xpl->add_xpl_callback(id => "logger",
                       self_skip => 0, targetted => 0,
                       callback => \&log,
                       filter => {
                                  message_type => 'xpl-trig',
	                              class => 'security',
                                  class_type => 'zone',
                                  });
 
my $oldsecondes = 0;
my $oldetat = "rien";
 
# Run the main loop
$xpl->main_loop();
 
# The callback to log the incoming messages
sub log {
  my %p = @_;
  my $msg = $p{message};
  my $peeraddr = $p{peeraddr};
  my $peerport = $p{peerport};  
  my $secondes = time();
 
	if(($oldetat ne $msg->state) && ($secondes>$oldsecondes+4) && ($msg->zone eq "powercode.bba0e9")){	#Ignore si l'état est le même que le précédent et attend 4 secondes pour éviter les répétitions et vérifie que le détecteur est bien celui de la porte.
		if($msg->state eq "true"){	#Porte ouverte
			#Do something here
			print "\nPorte ouverte \n";
			#Mise à jour dans HomeSeer
			system('curl -d "scriptcmd=hs.ExecX10%20%22Y6%22%2c%20%22on%22%2c%200%2c%200&runscript=Execute%20Command&ref_page=ctrl" http://192.168.10.12 >/dev/null 2>&1');	
		}
		elsif($msg->state eq "false"){	#Porte fermée
			#Do something here
			print "\nPorte fermee \n";
			#Mise à jour dans HomeSeer
			system('curl -d "scriptcmd=hs.ExecX10%20%22Y6%22%2c%20%22off%22%2c%200%2c%200&runscript=Execute%20Command&ref_page=ctrl" http://192.168.10.12 >/dev/null 2>&1');	
		}
 
  $oldsecondes = $secondes;
  $oldetat = $msg->state;	
	}
  return 1;
};
 
# send a "hbeat.end" message on exit
END { defined $xpl && $xpl->send_hbeat_end(); }

Je ne le détaille pas plus, je pense que c’est assez clair. Sur demande, je peux apporter plus d’explication.
J’ai nommé ce script xpl-porte.pl et enregistré dans /usr/bin/
Pensez au daemon de supervision qui va bien.

Remarque : Ce script peut également être utilisé pour avec un détecteur de mouvement. Dans ce cas, seul les messages state=true seront utiles.

Conclusion

Plus besoin de se soucier de quoi que ce soit, il suffit de laisser la porte entre-ouverte pour ne pas être enfermé dehors.