Détection de Présence basée sur IP

Issu d’un article du wiki de Domoticz et comme le sujet court sur le forum depuis quelque jours, je vous propose ma traduction de l’article en question concernant la détection de présence basée sur une IP.

images Alarme

 

Objectif

Ce script activera un switch virtuel lorsque un périphérique IP sera présent dans votre réseau et l’inactivera dès que ce périphérique IP aura disparu du réseau. Vous pouvez utiliser cela pour savoir si une personne (et surtout son téléphone) arrive dans votre réseau (cela nécessite une IP fixe sur le smartphone)

Cela est utilisable également pour savoir si votre NAS, Serveur … est up ou down.

Bien sur on pourra déclencher les événements classiques (action on , action off,scripts ..)

Prérequis

Ce mécanisme ne fonctionne que pour  des périphériques  ayant une IP fixe ou un bail DHCP statique.

Utilisez la configuration de vos équipements, de votre routeur ou celle de vos smartphones dans les paramètres wifi pour assigner des ip fixes .

Exemple d’un routeur 788 technicolor OVH

ip_fixe

Domoticz  – Matériel et  switches virtuels

Nous avons besoin d’un interrupteur dont l’état basculera en fonction de la présence d’une IP. Créons un interrupteur virtuel.

Il faut avoir activé auparavant un matériel de type « Dummy ».

Cette manip n’est à faire qu’une seule fois dans Domoticz pour activer les matériels virtuels et y accrocher tous nos interrupteurs (ou autres périphériques) virtuels.

  • Dans l’onglet « Matériel » , donnez un nom à votre matériel virtuel  ‘Dummy dev’ pour moi.
  • Choisissez ‘Dummy (Does nothing, use for virtual switches only)’  dans la liste déroulante.
  • Laissez  ‘Délai d’attente des données’ à « Désactivé. Cliquez  sur « Ajouter »

virtual device

Créons l’interrupteur virtuel

Rendez vous dans l’onglet des interrupteurs, puis « Ajout Manuel » en haut à gauche.

  • Choisissez le matériel virtuel crée plus haut
  • Donnez un nom explicite
  • Switch type sera ‘On/Off’
  • Le Type ‘X10’. Pourr ‘House code’ and ‘Unit code’, choisissez n’importe quoi
  • Laissez ‘Main Device’.
  • Validez, il se rajoute dans la liste des interrupteurs
  • En cliquant sur « Editer » ,on peut aussi cocher la case « Protégé » pour éviter les clicks manuels dans l’interface et ainsi n’autoriser que les scripts à agir sur ce switch.

Virtual_switchProtege

Nous avons besoin du numéro de ce périphérique Domoticz.

Allez dans ‘Configuration’ puis ‘Dispositifs », retrouvez l’équipement en question en notez son ID.

Domoticz ID

Domoticz ID

Bien sur si il y a plusieurs smartphones refaites cette creation autant que nécessaire. Notez chaque fois le bon ID.

LE script

Pourquoi ce script ci plutôt que d’autres ?

Au lancement il vérifie que l’état actuel du périphérique est le même (ou pas) que l’état indiqué dans Domoticz puis il reste actif en permanence pour scruter le changement d’état.

L’intérêt de celui ci est qu’il prend 4 paramètres qui sont bien commodes :

./checkip.py  192.168.1.76 93 20 300

  • L’adresse  IP du périphérique à interroger (Ici ‘192.168.1.76’)
  • L’ID du virtual switch (’93’)
  • L’intervalle en secondes pendant lequel on interroge pour savoir si le périphérique est présent ou non (20).
  • La ‘cool-down’ period (secondes). C’est le délai de non réponse du périphérique, si il ne répond pas dans ce délai, alors on décide qu’il est OFF (300).
  • Si au bout de 300 secondes il ne réponds pas alors OFF

Copiez ce script dans le dossier \home\pi\domoticz\scripts\  sous le nom que vous voulez (checkip.py pour moi)

Changez juste  l’adresse de votre Domoticz dans les settings et l’éventuel user/ motdepasse

# Settings for the domoticz server
domoticzserver="192.168.2.1:8080"
domoticzusername = ""
domoticzpassword = ""
[codesyntax lang="python"]
#!/usr/bin/python
#   Title: check_device_online.py
#   Author: Chopper_Rob
#   Date: 27-10-2014
#   Info: Checks the presence of the given device on the network and reports back to domoticz
#   URL : https://www.chopperrob.nl/domoticz/5-report-devices-online-status-to-domoticz
#   Version : 1.4
 
import sys
import datetime
import time
import os
import subprocess
import urllib2
import json
import base64
 
# Settings for the domoticz server
domoticzserver="192.168.1.81:8080"
domoticzusername = ""
domoticzpassword = ""
 
# DO NOT CHANGE BEYOND THIS LINE
if len(sys.argv) != 5 :
  print ("Not enough parameters. Needs %Host %Switchid %Interval %Cooldownperiod.")
  sys.exit(0)
 
device=sys.argv[1]
switchid=sys.argv[2]
interval=sys.argv[3]
cooldownperiod=sys.argv[4]
previousstate=-1
lastsuccess=datetime.datetime.now()
lastreported=-1
base64string = base64.encodestring('%s:%s' % (domoticzusername, domoticzpassword)).replace('\n', '')
domoticzurl = 'http://'+domoticzserver+'/json.htm?type=devices&filter=all&used=true&order=Name'
 
if int(subprocess.check_output('ps x | grep \'' + sys.argv[0] + ' ' + sys.argv[1] + '\' | grep -cv grep', shell=True)) > 2 :
 print (datetime.datetime.now().strftime("%H:%M:%S") + "- script already running. exiting.")
 sys.exit(0)
 
def domoticzstatus ():
  json_object = json.loads(domoticzrequest(domoticzurl))
 
  if json_object["status"] == "OK":
    for i, v in enumerate(json_object["result"]):
      if json_object["result"][i]["idx"] == switchid and "Lighting" in json_object["result"][i]["Type"] :
        if json_object["result"][i]["Status"] == "On": 
          status = 1
        if json_object["result"][i]["Status"] == "Off": 
          status = 0
  return status
 
def domoticzrequest (url):
  request = urllib2.Request(url)
  request.add_header("Authorization", "Basic %s" % base64string)
  response = urllib2.urlopen(request)
  return response.read()
 
print (datetime.datetime.now().strftime("%H:%M:%S") + "- script started.")
 
 
 
lastreported = domoticzstatus()
if lastreported == 1 :
  print (datetime.datetime.now().strftime("%H:%M:%S") + "- according to domoticz, " + device + " is online")
if lastreported == 0 :
  print (datetime.datetime.now().strftime("%H:%M:%S") + "- according to domoticz, " + device + " is offline")
 
while 1==1:
  currentstate = subprocess.call('ping -q -c1 -W 1 '+ device + ' > /dev/null', shell=True)
 
  if currentstate == 0 : lastsuccess=datetime.datetime.now()
  if currentstate == 0 and currentstate != previousstate and lastreported == 1 : 
    print (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, no need to tell domoticz")
  if currentstate == 0 and currentstate != previousstate and lastreported != 1 :
    if domoticzstatus() == 0 :
      print (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, tell domoticz it's back")
      domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=On&level=0")
    else:
      print (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, but domoticz already knew")
    lastreported=1
 
  if currentstate == 1 and currentstate != previousstate :
    print (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, waiting for it to come back")
 
  if currentstate == 1 and (datetime.datetime.now()-lastsuccess).total_seconds() > float(cooldownperiod) and lastreported != 0 :
    if domoticzstatus() == 1 :
      print (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, tell domoticz it's gone")
      domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=Off&level=0")
    else:
      print (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, but domoticz already knew")
    lastreported=0
 
  time.sleep (float(interval))
 
  previousstate=currentstate
[/codesyntax]

Dans un terminal dans le dossier \home\pi\domoticz\scripts , faites un chmod +x checkip.py.

Lancer ce script au boot de la machine

Dans un terminal,lancez crontab -e.

Dans l’écran ajoutez une ligne pour chaque périphérique à interroger

@reboot sudo /home/pi/domoticz/scripts/checkip.py 192.168.1.76 93 10 120
@reboot sudo /home/pi/domoticz/scripts/checkip.py 192.168.1.70 94 10 900

Faites CTRL O (pas zéro) puis entrée

Expérimentons

Tous les pc,serveurs, smartphones (android, ios) ne se comportement pas de la même façon , il faut ajuster la cool-down period (4eme valeur) en fonction de chaque matériel.

Car par exemple sur Ios , le Wifi est coupé quand l’écran est en veille, alors que sur Android non , le wifi est toujours ON, bref bricolez …

Ensuite déclenchez vos événements par les dispositifs esclaves, les action on/off, scripts,….

Bon jeu

 

Pour toute question technique concernant cet article, veuillez utiliser les forum situés à https://easydomoticz.com/forum/
Posted in domoticz, domotique, raspberry, scripts and tagged , , , , , , , .

21 Comments

  1. salut,

    D’abord bravo pour ce site !
    J’ai essayé la méthode décrite ci-dessus et ça ne marche pas, du coup pour investiquer j’ai lancé la commande cron dans le terminal et celle-ci se solde par une erreur : local variable ‘status’ referenced before assignment. sur le site de chopper rob quelqu’un évoque le même problème mais je n’ai pas trouvé la solution !! si quelqu’un a une piste je suis preneur !

    Par avance merci,

  2. Bonjour,
    Merci pour les compliments !
    Pour l’erreur une idée me vient en relisant le script cherche la ligne
    if json_object[« status »] == « OK »:
    et remplace par
    if json_object[« Status »] == « OK »:

    le status avec un S majuscule et dis moi si c’est OK

  3. Bonjour,

     

    Je débute dans l’univers de la domotique. Je parcours donc les forums pour apprendre et voir les possibilités.

    Tout d’abord, félicitation pour ton engagement et ton partage. Ce topic est particulièrement intéressant.

    J’essaye de le mettre en place et je me pose 2 questions :

    – A quoi sert le mode « protégé » que tu as défini dans l’interrupteur virtuel ?

    – Le script est en place sur ma framboise. Il réponds bien au changement d’état de mon smartphone lorsque je coupe le wifi de ce dernier.

    12:38:51- script started.
    12:38:51- according to domoticz, X.X.X.X is online
    12:38:52- X.X.X.X offline, waiting for it to come back
    12:39:46-X.X.X.X online, no need to tell domoticz

    Cependant, l’info ne remonte pas dans domoticz.

    Et effectivement, je ne vois pas par quel biais elle est censée remonter ??? (C’est précisément ma deuxième question)

    Le script a beau être présent dans le dossier script de l’installation de domoticz, ne faut il pas le « brancher » à l’interrupteur virtuel et éventuellement déclarer des variables pour interfacer le script avec domoticz ?

     

    Merci pour ton aide

    J’

  4. Merci pour les compliments.
    Concernant le mode protégé il est dit dans l’article

    on peut aussi cocher la case « Protégé » pour éviter les clicks manuels dans l’interface et ainsi n’autoriser que les scripts à agir sur ce switch.

    Quand à la liaison entre le script et Domoticz, tu remarqueras que
    1- dans le script tu as un bloc

    # Settings for the domoticz server
    domoticzserver= »192.168.1.81:8080″
    domoticzusername = «  »
    domoticzpassword = «  »

    ou tu dois placer IP, port, usr/password de ton Domoticz

    2- Tu dois appeler le script avec 4 arguments : tels que précisés dans l’article

    l’adresse IP du serveur que l’on veut tester,
    numéro d’idx du virtual switch
    nombre de secondes d’interrogation du peripherique IP
    delai de non reponse

    ./checkip.py 192.168.1.76 93 20 300

    L’adresse IP du périphérique à interroger (Ici ‘192.168.1.76’)
    L’ID du virtual switch (’93’)
    L’intervalle en secondes pendant lequel on interroge pour savoir si le périphérique est présent ou non (20).
    La ‘cool-down’ period (secondes). C’est le délai de non réponse du périphérique, si il ne répond pas dans ce délai, alors on décide qu’il est OFF (300).
    Si au bout de 300 secondes il ne réponds pas alors OFF

    Voila j’espère que cela roulera comme cela sinon reviens faire un tour ici
    Bonne soirée

  5. Salut patrice,

    je prends la suite de Sam

    => en remplaçant status par Status, d’autre soucis dans le script :

    20:57:39- script started.
    Traceback (most recent call last):
    File « ./checkip.py », line 65, in <module>
    lastreported = domoticzstatus()
    File « ./checkip.py », line 46, in domoticzstatus
    if json_object[« Status »] == « OK »:
    KeyError: ‘Status’

     

    Merci d’avance!

     

     

  6. Bonsoir
    L’erreur signifie qu’il n’a pas pu trouver ton Domoticz donc une erreur ici

    # Settings for the domoticz server
    domoticzserver= »192.168.1.81:8080″
    domoticzusername = «  »
    domoticzpassword = «  »

    tu as oublie de changer, l’ip , le port , tu as mis un mot de passe …

  7. Bonsoir

    Merci pour ce script et ce tutoriel

    Le script est copié, il fonctionne mais pas moyen de faire remonter l’info sur les interrupteurs

    il reste toujours sur OFF

    Merci d’avance

  8. Bonjour
    As tu changé les adreses IP de mon domoticz pourle tien ?
    as tu mis des user et password dans ton domoticz?
    que se passe t’il lorsque tu tapes directement en mode console le nom de ton script : des erreurs, rien ?

  9. Bonjour

    j’ai changé l’ IP et le compte domoticz

    voici le retour de la commande
    root@raspberrypi:/home/pi/domoticz/scripts# ./checkip.py 192.168.0.100 47 60 120
    13:17:23- script started.
    13:17:23- according to domoticz, 192.168.0.100 is online
    13:17:24- 192.168.0.100 offline, waiting for it to come back
    ^CTraceback (most recent call last):
      File « ./checkip.py », line 95, in <module>
        time.sleep (float(interval))
    KeyboardInterrupt

    Merci pour ta réponse

  10. et le crontab
    */10 * * * *  /home/pi/domoticz/scripts/checkip.py 192.168.0.100 47 60 120
    */10 * * * *  /home/pi/domoticz/scripts/checkip.py 192.168.0.104 48 60 120

  11. Donc on est d’accord dans le script tu as modifie la ligne
    – domoticzserver= »192.168.1.81:8080″ par l’adresse ip de TON domoticz
    – 192.18.0.100 est l’adresse ip du telephone ou materiel dont tu testes la présence
    – 47 est l’index du widget interrupteur qui devra basculer à ON
    C’est ca ?

    Ensuite tu n’a pas répondu à ma question de mot de passe et user de protection de Domoticz , il y en a ?

  12. hello

    oui, j’ai remplacé l’adresse ip par celle de mon domoticz, ajouté mon compte et mon mot de passe, je n’ai pas de user protection de domoticz

    192.18.0.100 est l’adresse ip materiel et 47 est l’index du widget de l’interrupteur qui doit passer à on

    voici le résultat de la commande :
    pi@raspberrypi:~/domoticz/scripts$ ./checkip.py 192.168.0.100 47 60 120
    19:29:32- script started.
    19:29:32- according to domoticz, 192.168.0.100 is offline
    19:29:32- 192.168.0.100 online, tell domoticz it’s back
    ^CTraceback (most recent call last):
      File « ./checkip.py », line 95, in <module>
        time.sleep (float(interval))
    Merci
    Laurent

  13. Bonjour
    oui c’est bizarre ici ça marche correctement et ça bascule bien l’interrupteur en question
    je teste la présence de 192.168.1.93 , j’active l(interuupteur 112 au bout de 20 sec et 10 sec de delai de grace
    j’ai joue a connecter/deconnecter mon telephone et tout se passe bien
    pi@domoticz ~/domoticz/scripts $ ./checkip.py 192.168.1.93 112 20 10
    10:13:56- script started.
    10:13:56- according to domoticz, 192.168.1.93 is offline
    10:13:56- 192.168.1.93 online, tell domoticz it's back
    10:14:37- 192.168.1.93 offline, waiting for it to come back
    10:14:38- 192.168.1.93 offline, tell domoticz it's gone
    10:15:40- 192.168.1.93 online, tell domoticz it's back

    essaie de mettre des print dans le programme python pour voir d’ou ca vient

  14. hello

    Maintenant, j’ai mis en place un script Lua et tout fonctionne correctement.

    je continuerai à tester ton script plus tard, il doit marcher !!!

    Merci pour ton aide

     

  15. Bonjour,

    Je viens pour donner la solution toute simple pour ceux qui quand il run dans le terminal ./checkip.py 192.168.0.100 47 60 120 et que tout ce passe à merveille à ce moment là et une fois le terminal fermé plus rien !

    La solution uniquement dans le crontab -e à la place de

    0 * * * * sudo /home/pi/domoticz/scripts/checkip.py 192.168.1.76 93 10 120

    faites comme ceci

    0/10 * * * * /home/pi/domoticz/scripts/ 192.168.1.76 93 10 120

    Vérifiez quand même que checkip.py a les bonnes permissions 755

  16. Salut,

    tout fonctionnait bien jusqu’à maintenant.
    Je ne sais pas ce qu’il s’est passé, mais maintenant le script ne fonctionne plus.
    Et quand je le lance à la main dans un terminal, j’obtiens tous ces messages d’erreurs… Et j’y comprends rien…
    Une idée?

     

    23:10:57- pid file exists
    23:10:57- Seems to be an old file, ignoring.
    23:10:57- script started.
    Traceback (most recent call last):
    File « ./presence_IP.py », line 102, in <module>
    lastreported = domoticzstatus()
    File « ./presence_IP.py », line 80, in domoticzstatus
    json_object = json.loads(domoticzrequest(domoticzurl))
    File « ./presence_IP.py », line 97, in domoticzrequest
    response = urllib2.urlopen(request)
    File « /usr/lib/python2.7/urllib2.py », line 154, in urlopen
    return opener.open(url, data, timeout)
    File « /usr/lib/python2.7/urllib2.py », line 437, in open
    response = meth(req, response)
    File « /usr/lib/python2.7/urllib2.py », line 550, in http_response
    ‘http’, request, response, code, msg, hdrs)
    File « /usr/lib/python2.7/urllib2.py », line 475, in error
    return self._call_chain(*args)
    File « /usr/lib/python2.7/urllib2.py », line 409, in _call_chain
    result = func(*args)
    File « /usr/lib/python2.7/urllib2.py », line 558, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
    urllib2.HTTPError: HTTP Error 401: Unauthorized

  17. Bonjour,

    ce message vous dit-il quelque chose ?

    ./checkip.py: 1: ./checkip.py: import: not found
    ./checkip.py: 2: ./checkip.py: import: not found
    ./checkip.py: 3: ./checkip.py: import: not found
    ./checkip.py: 4: ./checkip.py: import: not found
    ./checkip.py: 5: ./checkip.py: import: not found
    ./checkip.py: 6: ./checkip.py: import: not found
    ./checkip.py: 7: ./checkip.py: import: not found
    ./checkip.py: 8: ./checkip.py: import: not found
    ./checkip.py: 12: ./checkip.py: domoticzusername: not found
    ./checkip.py: 13: ./checkip.py: domoticzpassword: not found
    ./checkip.py: 16: ./checkip.py: Syntax error: word unexpected (expecting « ) »)

    Merci de votre réponse éclairé 😉

  18. Merci pour cet article très intéressant!

    Il y a cependant un truc que j’ai pas compris. A l’aide du crontab, tu semble lancer le script très fréquement. Or dans le script, il y a une boucle infini (1 ==1) donc le script ne va jamais se terminer. Mais alors pourquoi le lancer plusieurs fois? Dans l’état actuel, la raspberry doit alors lancer un nouveau script à chaque fois de manière infini, et donc augmentation des scripts qui tournent en parrallèle pour faire la même chose.

  19. Bonjour
    Oui tu as raison, j’avais oubliè de modifier l’article en question pour faire executer le script juste au reboot en utilisant le @reboot du crontab.

    J’ai corrigè,
    Merci de ta lecture attentive.

  20. Bonjour,
    Voici les messages d’erreurs lorsque je lance le script à la main.
    Une idée?
    Merci et merci pour ce tuto

    pi@domoticz:~ $ /home/pi/domoticz/scripts/Perso/check_ip.py 192.168.0.203 15 60 300
    23:06:23- script started.
    Traceback (most recent call last):
    File « /home/pi/domoticz/scripts/Perso/check_ip.py », line 64, in
    lastreported = domoticzstatus()
    File « /home/pi/domoticz/scripts/Perso/check_ip.py », line 52, in domoticzstatus
    return status
    UnboundLocalError: local variable ‘status’ referenced before assignment

Comments are closed.