Soms is het handig wanneer Domoticz weet of er iemand thuis is, zodat je bijvoorbeeld al je verlichting kunt uitschakelen wanneer er niemand thuis is. Nu kun je natuurlijk je hele huis volhangen met bewegingsdetectoren, maar dat wordt toch een dure grap.

Aangezien zo’n beetje iedereen tegenwoordig een smartphone heeft, die verbonden is met het wifi-netwerk thuis, kunnen we de connectie van deze smartphones met het wifi-netwerk gebruiken om te kijken of iemand thuis is.

Stap 1:Virtuele switches creëren voor je smartphones

  • Open de webinterface van Domoticz.
  • Klik op Instellingen en vervolgens op Hardware.
  • Voer nu als naam Smartphones in.
  • Selecteer het type Dummy en klik vervolgens op Toevoegen.
  • Klik nu op het tabblad Schakelaars.
  • Klik linksboven op de knop Handmatig.
  • Kies nu als Hardware Smartphones.
  • Als naam voer je een naam in die verwijst naar een smartphone van iemand in je huis.
    Bijvoorbeeld: Rutger’s iPhone.
  • Bij schakelaar-type kies je voor On/Off.
  • Als type kies je X10, bij House code kies je A en bij Unit code kies je 1.
  • Bij Als kies je Hoofdapparaat. Klik tot slot op toevoegen.
  • Als je meerdere smartphones in huis hebt, herhaal je de laatste 6 stappen voor elke smartphone.

Stap 2: Software installeren via SSH

  • Log in op je domoticz-server via SSH.
  • Typ het volgende commando om Python en apin te installeren:
    sudo apt-get install python arping
  • We gaan Python gebruiken om via arping de verschillende smartphones te pingen. Veel smartphones reageren niet op een ping wanneer ze stand-by staan. In tegenstelling tot het standaard ping-commando stuurt arping een ‘apr-whois’ uit waar de smartphones ook op reageren wanneer ze stand-by staan.
  • Domoticz-gebruiker Chopper Rob heeft een handig stukje Python-code geschreven dat een smartphone pingt en vervolgens communiceert met Domoticz. Maak een bestand, genaamd check_device_online.py aan in de map /home/pi/domoticz/scripts. Je kunt dit eenvoudig doen door de onderstaande code te kopiëren. (CTRL+c / CMD+C). Vervolgens toets je het volgende command in via je SSH-sessie:
  • nano /home/pi/domoticz/scripts/check_device_online.py
  • De nano teksteditor wordt nu geopend. Plak nu de code in het bestand en toets CTRL+x om het bestand op te slaan en de teksteditor af te sluiten.
#!/usr/bin/python
#   Title: check_device_online.py
#   Author: Chopper_Rob
#   Date: 25-02-2015
#   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.6.2
 
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.5:8080"
domoticzusername = "admin"
domoticzpassword = "admin"
domoticzpasscode = "protectedswitch"
 
# If enabled. The script will log to the file _.log
# Logging to file only happens after the check for other instances, before that it only prints to screen.
log_to_file = False
 
# The script supports two types to check if another instance of the script is running.
# One will use the ps command, but this does not work on all machine (Synology has problems)
# The other option is to create a pid file named _.pid. The script will update the timestamp
# every interval. If a new instance of the script spawns it will check the age of the pid file.
# If the file doesn't exist or it is older then 3 * Interval it will keep running, otherwise is stops.
# Please chose the option you want to use "ps" or "pid", if this option is kept empty it will not check and just run.
check_for_instances = "pid"
 
 
 
# 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 check_for_instances.lower() == "pid":
  pidfile = sys.argv[0] + '_' + sys.argv[1] + '.pid'
  if os.path.isfile( pidfile ):
    print datetime.datetime.now().strftime("%H:%M:%S") + "- pid file exists"
    if (time.time() - os.path.getmtime(pidfile)) < (float(interval) * 3):
      print datetime.datetime.now().strftime("%H:%M:%S") + "- script seems to be still running, exiting"
      print datetime.datetime.now().strftime("%H:%M:%S") + "- If this is not correct, please delete file " + pidfile
      sys.exit(0)
    else:
      print datetime.datetime.now().strftime("%H:%M:%S") + "- Seems to be an old file, ignoring."
  else:
    open(pidfile, 'w').close() 
 
if check_for_instances.lower() == "ps":
  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 log(message):
  print message
  if log_to_file == True:
    logfile = open(sys.argv[0] + '_' + sys.argv[1] + '.log', "a")
    logfile.write(message + "\n")
    logfile.close()
 
def domoticzstatus ():
  json_object = json.loads(domoticzrequest(domoticzurl))
  status = 0
  switchfound = False
  if json_object["status"] == "OK":
    for i, v in enumerate(json_object["result"]):
      if json_object["result"][i]["idx"] == switchid:
        switchfound = True
        if json_object["result"][i]["Status"] == "On": 
          status = 1
        if json_object["result"][i]["Status"] == "Off": 
          status = 0
  if switchfound == False: print (datetime.datetime.now().strftime("%H:%M:%S") + "- Error. Could not find switch idx in Domoticz response. Defaulting to switch off.")
  return status
 
def domoticzrequest (url):
  request = urllib2.Request(url)
  request.add_header("Authorization", "Basic %s" % base64string)
  response = urllib2.urlopen(request)
  return response.read()
 
log (datetime.datetime.now().strftime("%H:%M:%S") + "- script started.")
 
lastreported = domoticzstatus()
if lastreported == 1 :
  log (datetime.datetime.now().strftime("%H:%M:%S") + "- according to domoticz, " + device + " is online")
if lastreported == 0 :
  log (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)
  currentstate = subprocess.call('sudo arping -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 : 
    log (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 :
      log (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" + "&passcode=" + domoticzpasscode)
    else:
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, but domoticz already knew")
    lastreported=1
 
  if currentstate == 1 and currentstate != previousstate :
    log (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 :
      log (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" + "&passcode=" + domoticzpasscode)
    else:
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, but domoticz already knew")
    lastreported=0
 
  time.sleep (float(interval))
 
  previousstate=currentstate
  if check_for_instances.lower() == "pid": open(pidfile, 'w').close()

Stap 3: Het script inplannen met Cron

Het script dat we zojuist gemaakt hebben, kan gaan we om de tien minuten laten controleren of een bepaalde smartphone verbonden is met het netwerk. Dit doen we door eerst onze crontab te openen:

crontab -e

Vervolgens voeren we de volgende regel helemaal onderin toe:

*/10 * * * * /usr/bin/python /home/pi/domoticz/scripts/check_device_online.py 192.168.1.10 23 10 300

Deze regel zorgt er voor dat het apparaat met IP-adres 192.168.1.10 (parameter 1) de dummy-schakelaar met IDX 23 (parameter 2) om de 10 minuten (parameter 3) gepingd wordt.

De IDX kun je achterhalen in Domoticz via Instellingen -> Apparaten. Er wordt een cooldown-periode (parameter 4) gehanteerd van 300 seconden. Binnen die tijd wordt er wel gecontroleerd of het device aanwezig is, maar wordt de status niet doorgegeven aan Domoticz. De cooldown-periode is met name belangrijk wanneer je een iPhone gebruikt, omdat deze zijn Wifi-verbinding regelmatig uitschakelt om de accu te sparen. Ik heb redelijk succes geboekt met 300 seconden, maar wellicht werkt een langere periode beter, dat moet ik nog proberen.

Als je meerdere smartphones wilt controleren, dan voeg je voor elke smartphone een eigen regel toe in de crontab, natuurlijk met elk zijn eigen IP-adres.

Router instellen

Je smartphone krijgt zijn IP-adres van de router via DHCP. Dit is niet altijd hetzelfde IP-adres. Wanneer je smartphone een ander IP-adres krijgt, zal het script niet meer werken omdat het een IP-adres probeert te pingen dat de smartphone niet meer heeft.

In je router heb je de mogelijkheid om static leases in te stellen. Hierdoor krijgt een device op basis van zijn MAC-adres altijd hetzelfde IP-adres uitgedeeld, omdat het IP-adres exclusief voor het device reserveer is. Raadpleeg hiervoor de handleiding van je router.

Als je meerdere smartphones gebruikt, kan het handig zijn om nog een dummy-schakelaar aan te maken. Deze kun je dan via Blockly in Domoticz laten schakelen als één van de smartphone dummy-schakelaars actief is. Deze nieuwe dummy-schakelaar noem je dan bijvoorbeeld “Iemand thuis”. Daarna kun je de status van deze schakelaar gebruiken in andere gebeurtenissen.

Reacties