Improved Presence Detection / Ping Script:

Python and python framework

Moderator: leecollings

Post Reply
borcon
Posts: 20
Joined: Thursday 05 January 2017 11:15
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Contact:

Improved Presence Detection / Ping Script:

Post by borcon »

Hello,

i have something for you.
Many people use the phyton ping script from wiki.
https://www.domoticz.com/wiki/Presence_detection
But i missed some functions. So it was time to improve it.

New Functions:
- Sync Status

Old script does only set the device status. If the switch was directly changed in domoticz, the script doesn't get the informations back. If device is switched off in domoticz, then the script will it switch back to on.
You can control if the script should directly switch back to on or wait for x rounds or disable sync.
Control flags inside the script: syncstate and waitcount

- Support for dimmers
Old script set the dimmer level/status always back to on or off

- Ignore the on/off action in device
You have to start the script with a further parameter (NoOnOffEvent).
%Host %Switchid %Interval %Cooldownperiod %NoOnOffEvent
1 = NoOnOffEvent, 0 = Default
Important: Lua eventsystem does always get a device change

- New Action Variable
In somecases you want to switch a device without the eventsystem (lua/blocky/...).
If the script will change a device status then first a variable will be updated/created and set to 1.
You can use this variable in lua/blocky/... . If variable = 1 then "do nothing".
But you have to set the variable back to 0.
You can enable/disable the variable inside the script- ping_domo_variable = True
Variablename: Ping_IPADDRESS

- Installation
Open crontab with "crontab -e" in ssh and add your lines with your needed ips
# Device 1
*/10 * * * * sudo /home/pi/domoticz/scripts/custom/check_device_online.py 192.168.178.3 325 30 60 0
# Device 2
*/10 * * * * sudo /home/pi/domoticz/scripts/custom/check_device_online.py 192.168.178.2 327 30 30 0

Code: Select all

#!/usr/bin/python
#   Title: check_device_online.py
#   Author: Chopper_Rob, modified by borcon
#
#   Date: 19-07-2017
#   Version : 1.7.0

import sys
import datetime
import time
import os
import subprocess
import urllib2
import json
import base64
 
# Settings for the domoticz server
domoticzserver="127.0.0.1:8080"
domoticzusername = ""
domoticzpassword = ""
domoticzpasscode = ""

# Create in domoticz a variable with the name "Ping_YOURIPADDRESS"
# If the script will change a switch in domoticz, then
# first the variable will be set from 0 to 1.
# Then you can use the variable in lua
ping_domo_variable = True

# Sync device state with domoticz.
# Time to wait to set correct device status in domoticz, if domoticz state and last reported state are different
# This may happens, if someone changes the dummy device state in domoticz
# %Interval * waitcount = is the time to wait to set the device status
# Example 10 seconds interval * 5 = 50 seconds
syncstate = 1
waitcount = 2
 
# 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 = True
 
# 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) != 6 :
  print ("Not enough parameters. Needs %Host %Switchid %Interval %Cooldownperiod %NoOnOffEvent.")
  sys.exit(0)
 
device=sys.argv[1]
switchid=sys.argv[2]
interval=sys.argv[3]
cooldownperiod=sys.argv[4]
noonoffevent=int(sys.argv[5])
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'
wait = 0
 
if check_for_instances.lower() == "pid":
  #pidfile = sys.argv[0] + '_' + sys.argv[1] + '.pid'
  pidfile = '/run/check_device_online.py_' + sys.argv[1] + '.pid'
  if os.path.isfile( pidfile ):
    print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- pid file exists"
    if (time.time() - os.path.getmtime(pidfile)) < (float(interval) * 3):
      print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- script seems to be still running, exiting"
      print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- If this is not correct, please delete file " + pidfile
      sys.exit(0)
    else:
      print datetime.datetime.now().strftime("%Y/%m/%d %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("%Y/%m/%d %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 "Set Level" in json_object["result"][i]["Status"]: 
          status = 1
        if json_object["result"][i]["Status"] == "Off": 
          status = 0
  if switchfound == False: print (datetime.datetime.now().strftime("%Y/%m/%d %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("%Y/%m/%d %H:%M:%S") + "- script started.")
 
lastreported = domoticzstatus()
if lastreported == 1 :
  log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- according to domoticz, " + device + " is online")
if lastreported == 0 :
  log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- according to domoticz, " + device + " is offline")

if ping_domo_variable == True:  
  # Create variable in domoticz, if already exist, no problem
  domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=saveuservariable&vname=Ping_" + device + "&vtype=0&vvalue=0" + "&passcode=" + domoticzpasscode)
  # Set variable in domoticz to 0
  domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=0" + "&passcode=" + domoticzpasscode)

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)
  
  # currentstate     --> 1 = offline , 0 = online
  # previousstate    --> 1 = offline , 0 = online
  # lastreported     --> 0 = offline , 1 = online
  # domoticzstatus() --> 0 = offline , 1 = online
    
  #log ("currentstate:" + str(currentstate)) 
  #log ("previousstate: " + str(previousstate)) 
  #log ("lastreported: " + str(lastreported)) 
  #log ("Domoticz State: " + str(domoticzstatus()))
  #log (" ")
 
  if currentstate == 0 : lastsuccess=datetime.datetime.now()
  if currentstate == 0 and currentstate != previousstate and lastreported == 1 : 
    log (datetime.datetime.now().strftime("%Y/%m/%d %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("%Y/%m/%d %H:%M:%S") + "- " + device + " online, tell domoticz it's back")
      if ping_domo_variable == True:
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=1" + "&passcode=" + domoticzpasscode)
      if noonoffevent == 0 :
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=On&level=0" + "&passcode=" + domoticzpasscode)
      else:
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid + "&nvalue=1&svalue=On" + "&passcode=" + domoticzpasscode)
    else:
      log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- " + device + " online, but domoticz already knew")
    lastreported=1
    wait = 0
 
  if currentstate == 1 and currentstate != previousstate :
    log (datetime.datetime.now().strftime("%Y/%m/%d %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("%Y/%m/%d %H:%M:%S") + "- " + device + " offline, tell domoticz it's gone")
      if ping_domo_variable == True:
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=1" + "&passcode=" + domoticzpasscode)
      if noonoffevent == 0 :
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=Off&level=0" + "&passcode=" + domoticzpasscode)
      else:
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid + "&nvalue=0&svalue=Off" + "&passcode=" + domoticzpasscode)
    else:
      log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- " + device + " offline, but domoticz already knew")
    lastreported=0
    wait = 0
  
  if syncstate == 1 and currentstate == previousstate :
    if lastreported != domoticzstatus() :
      wait += 1
      if waitcount <= wait :
        if currentstate == 1 :
          log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- " + device + " offline, domoticz state and last reported state are different, time to correct state to offline")
          if ping_domo_variable == True:
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=1" + "&passcode=" + domoticzpasscode)
          if noonoffevent == 0 :          
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=Off&level=0" + "&passcode=" + domoticzpasscode)
          else:
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid + "&nvalue=0&svalue=Off" + "&passcode=" + domoticzpasscode)
          lastreported=0
          wait = 0
        else:
          log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- " + device + " online, domoticz state and last reported state are different, time to correct state to online")
          if ping_domo_variable == True:
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=1" + "&passcode=" + domoticzpasscode)
          if noonoffevent == 0 :          
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=On&level=0" + "&passcode=" + domoticzpasscode)
          else:
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid + "&nvalue=1&svalue=On" + "&passcode=" + domoticzpasscode)
          lastreported=1
          wait = 0

  time.sleep (float(interval))
 
  previousstate=currentstate
  if check_for_instances.lower() == "pid": open(pidfile, 'w').close()
Have fun,

borcon
Last edited by borcon on Wednesday 08 November 2017 20:42, edited 1 time in total.
klaasnicolaas
Posts: 8
Joined: Monday 07 August 2017 1:29
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8153
Location: Alkmaar
Contact:

Re: Improved Presence Detection / Ping Script:

Post by klaasnicolaas »

If I test your script in my environment, I get this:

Code: Select all

Traceback (most recent call last):
  File "check_device_online.py", line 80, in <module>
    open(pidfile, 'w').close()
IOError: [Errno 13] Permission denied: '/run/check_device_online.py_192.168.2.7.pid'
I don't understand how to solve this, could you help?
Hardware/Setup:
- Dashticz V2
- Aeon Labs Z-Stick GEN5
- RFXtrx433E
- P1 Smart Meter
- 1x Fibaro Smoke Sensor
- 1x Fibaro Wall Plug
- KAKU Stuff
blauwebuis
Posts: 331
Joined: Wednesday 21 December 2016 9:11
Target OS: Raspberry Pi / ODroid
Domoticz version: current
Contact:

Re: Improved Presence Detection / Ping Script:

Post by blauwebuis »

@klaasnicolaas: I suspect you uploaded a new script over the old file? That has changed the permissions of that file (the owner), and now Domoticz is not allowed to open it anymore.

You can try to change the permission settings of the file. Right-mouse button on it from linux. Of use the terminal with the chmod or chown commands (google them, there are tutorials).

You can also try to run the script with the sudo command and see if it runs then. Sudo forces a file to be executed as if it was owned by the root user, who is allowed to do anything.
blauwebuis
Posts: 331
Joined: Wednesday 21 December 2016 9:11
Target OS: Raspberry Pi / ODroid
Domoticz version: current
Contact:

Re: Improved Presence Detection / Ping Script:

Post by blauwebuis »

@borcon or others: could this script become a python plugin perhaps?
klaasnicolaas
Posts: 8
Joined: Monday 07 August 2017 1:29
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8153
Location: Alkmaar
Contact:

Re: Improved Presence Detection / Ping Script:

Post by klaasnicolaas »

blauwebuis wrote: Thursday 26 October 2017 11:48 @klaasnicolaas: I suspect you uploaded a new script over the old file? That has changed the permissions of that file (the owner), and now Domoticz is not allowed to open it anymore.

You can try to change the permission settings of the file. Right-mouse button on it from linux. Of use the terminal with the chmod or chown commands (google them, there are tutorials).

You can also try to run the script with the sudo command and see if it runs then. Sudo forces a file to be executed as if it was owned by the root user, who is allowed to do anything.
Only problem is that I can not find this file: check_device_online.py_192.168.2.7.pid on the pi :(
And the file: check_device_online.py has permission: 755
Hardware/Setup:
- Dashticz V2
- Aeon Labs Z-Stick GEN5
- RFXtrx433E
- P1 Smart Meter
- 1x Fibaro Smoke Sensor
- 1x Fibaro Wall Plug
- KAKU Stuff
manjh
Posts: 748
Joined: Saturday 27 February 2016 12:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: NL
Contact:

Re: Improved Presence Detection / Ping Script:

Post by manjh »

This may be a bit off-topic, but definitely related.
Until now I have used a simple ping to detect if someone is present at home, so I can switch on the right level of lighting. Both my wife and I have our own smartphone with an IP address that is consistent.
But now that I have a VPN tunnel set up, we stay linked to our home network for security reasons. We keep the VPN tunnel linked.
This means that the phone will respond to a ping, even when we're both far away....

So I am looking for a different way.
Have looked at the "nut", but it costs more than I expected, and definitely more than a simple "trial" is worth.
It would be nice to have a bluetooth app running on the Android phones, to reply to a BT app in the Pi, same as with the nut.
But I cannot find anything like that.
Any ideas?
Hans
User avatar
jvdz
Posts: 2330
Joined: Tuesday 30 December 2014 19:25
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.107
Location: Netherlands
Contact:

Re: Improved Presence Detection / Ping Script:

Post by jvdz »

You don't need any BT app on the phone, just a BT dongle in the raspberry any you can check the presence with checking the presense of the phones BT mac.
Using it this way for quite a while now and is much more stable than IP ping.

Jos
New Garbage collection scripts: https://github.com/jvanderzande/GarbageCalendar
manjh
Posts: 748
Joined: Saturday 27 February 2016 12:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: NL
Contact:

Re: Improved Presence Detection / Ping Script:

Post by manjh »

jvdz wrote: Thursday 26 October 2017 20:40 You don't need any BT app on the phone, just a BT dongle in the raspberry any you can check the presence with checking the presense of the phones BT mac.
Using it this way for quite a while now and is much more stable than IP ping.

Jos
Jos, where did you get that dongle? Do you have a link?
Hans
manjh
Posts: 748
Joined: Saturday 27 February 2016 12:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: NL
Contact:

Re: Improved Presence Detection / Ping Script:

Post by manjh »

jvdz wrote: Thursday 26 October 2017 20:40 You don't need any BT app on the phone, just a BT dongle in the raspberry any you can check the presence with checking the presense of the phones BT mac.
Using it this way for quite a while now and is much more stable than IP ping.

Jos
Hang on, I have an R-Pi-3, that should have BT in it! Now only to find a way to use it? Did you use a script? How did you configure Domoticz?
Hans
User avatar
jvdz
Posts: 2330
Joined: Tuesday 30 December 2014 19:25
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.107
Location: Netherlands
Contact:

Re: Improved Presence Detection / Ping Script:

Post by jvdz »

I don't have a Pi3 and have read that some needed to disable it but when it is active I guess you could use it.
My LUA script is based on this idea: http://www.domoticz.com/forum/viewtopic ... +bluetooth

So I have a dummy switch and am using a LUA script which runs through crontab, that checks for the Bluetooth MAC and if not found the IP as backup.
It is setup that it can handle multiple phones, per scheduled process and am using 2 separate processes to check for the presence of 4 phone (2 phones each).
I can share the scripts I have when you want but maybe we should do that in another thread as I don't want to hyjack this one?

Jos
New Garbage collection scripts: https://github.com/jvanderzande/GarbageCalendar
manjh
Posts: 748
Joined: Saturday 27 February 2016 12:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: NL
Contact:

Re: Improved Presence Detection / Ping Script:

Post by manjh »

jvdz wrote: Thursday 26 October 2017 22:12 I don't have a Pi3 and have read that some needed to disable it but when it is active I guess you could use it.
My LUA script is based on this idea: http://www.domoticz.com/forum/viewtopic ... +bluetooth

So I have a dummy switch and am using a LUA script which runs through crontab, that checks for the Bluetooth MAC and if not found the IP as backup.
It is setup that it can handle multiple phones, per scheduled process and am using 2 separate processes to check for the presence of 4 phone (2 phones each).
I can share the scripts I have when you want but maybe we should do that in another thread as I don't want to hyjack this one?

Jos
Well, it sounds like exactly what I need! Another thread would be good, but you could also consider putting it into the Wiki so others can use it as well?
As for BT in the Pi: I haven't disabled anything, so I assume it is functional...
Hans
vgr2
Posts: 71
Joined: Monday 29 August 2016 12:02
Target OS: -
Domoticz version:
Contact:

Re: Improved Presence Detection / Ping Script:

Post by vgr2 »

Sounds good, will this also work with IPhone BT?
manjh
Posts: 748
Joined: Saturday 27 February 2016 12:49
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: NL
Contact:

Re: Improved Presence Detection / Ping Script:

Post by manjh »

It would be great if this would be in the Wiki as a step-by-step instruction! This sounds like a real improvement, and (assuming an R-Pi model 3) takes no investment at all! Virtually all smartphones support Bluetooth these days.
Hans
User avatar
jvdz
Posts: 2330
Joined: Tuesday 30 December 2014 19:25
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.107
Location: Netherlands
Contact:

Re: Improved Presence Detection / Ping Script:

Post by jvdz »

Cleaned up the script a but to make it more generic and posted it here: http://www.domoticz.com/forum/viewtopic ... 61&t=20088

Jos
New Garbage collection scripts: https://github.com/jvanderzande/GarbageCalendar
User avatar
Siewert308SW
Posts: 290
Joined: Monday 29 December 2014 15:47
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: The Netherlands
Contact:

Re: Improved Presence Detection / Ping Script:

Post by Siewert308SW »

@borcon

Offcourse for those who love to ping BT devices.
Your amended script can also be used to ping BT MAC addresses.
I personally use ChopperRob his first script to ping BT devices.

Below your script with just a small edit for BT ping.
Instead of using a IP you have to use the MAC address of BT device.

call the script like this in cron:
*/10 * * * * sudo python /home/pi/domoticz/scripts/python/bt_device_online.py 22:88:72:EE:26:51 13 60 90 1

Code: Select all

#!/usr/bin/python
#   Title: check_device_online.py
#   Author: Chopper_Rob, modified by borcon
#
#   Date: 19-07-2017
#   Version : 1.7.0

import sys
import datetime
import time
import os
import subprocess
import urllib2
import json
import base64
 
# Settings for the domoticz server
domoticzserver="127.0.0.1:8080"
domoticzusername = ""
domoticzpassword = ""
domoticzpasscode = ""

# Create in domoticz a variable with the name "Ping_YOURIPADDRESS"
# If the script will change a switch in domoticz, then
# first the variable will be set from 0 to 1.
# Then you can use the variable in lua
ping_domo_variable = True

# Sync device state with domoticz.
# Time to wait to set correct device status in domoticz, if domoticz state and last reported state are different
# This may happens, if someone changes the dummy device state in domoticz
# %Interval * waitcount = is the time to wait to set the device status
# Example 10 seconds interval * 5 = 50 seconds
syncstate = 1
waitcount = 2
 
# 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 = True
 
# 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) != 6 :
  print ("Not enough parameters. Needs %Host %Switchid %Interval %Cooldownperiod %NoOnOffEvent.")
  sys.exit(0)
 
device=sys.argv[1]
switchid=sys.argv[2]
interval=sys.argv[3]
cooldownperiod=sys.argv[4]
noonoffevent=int(sys.argv[5])
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'
wait = 0
 
if check_for_instances.lower() == "pid":
  #pidfile = sys.argv[0] + '_' + sys.argv[1] + '.pid'
  pidfile = '/run/check_device_online.py_' + sys.argv[1] + '.pid'
  if os.path.isfile( pidfile ):
    print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- pid file exists"
    if (time.time() - os.path.getmtime(pidfile)) < (float(interval) * 3):
      print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- script seems to be still running, exiting"
      print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- If this is not correct, please delete file " + pidfile
      sys.exit(0)
    else:
      print datetime.datetime.now().strftime("%Y/%m/%d %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("%Y/%m/%d %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 "Set Level" in json_object["result"][i]["Status"]: 
          status = 1
        if json_object["result"][i]["Status"] == "Off": 
          status = 0
  if switchfound == False: print (datetime.datetime.now().strftime("%Y/%m/%d %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("%Y/%m/%d %H:%M:%S") + "- script started.")
 
lastreported = domoticzstatus()
if lastreported == 1 :
  log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- according to domoticz, " + device + " is online")
if lastreported == 0 :
  log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- according to domoticz, " + device + " is offline")

if ping_domo_variable == True:  
  # Create variable in domoticz, if already exist, no problem
  domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=saveuservariable&vname=Ping_" + device + "&vtype=0&vvalue=0" + "&passcode=" + domoticzpasscode)
  # Set variable in domoticz to 0
  domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=0" + "&passcode=" + domoticzpasscode)

while 1==1:
  #currentstate = subprocess.call('ping -q -c1 -W 1 '+ device + ' > /dev/null', shell=True)
  currentstate = subprocess.call('sudo l2ping -c 1 -s 1 '+ device + ' > /dev/null', shell=True)
  
  # currentstate     --> 1 = offline , 0 = online
  # previousstate    --> 1 = offline , 0 = online
  # lastreported     --> 0 = offline , 1 = online
  # domoticzstatus() --> 0 = offline , 1 = online
    
  #log ("currentstate:" + str(currentstate)) 
  #log ("previousstate: " + str(previousstate)) 
  #log ("lastreported: " + str(lastreported)) 
  #log ("Domoticz State: " + str(domoticzstatus()))
  #log (" ")
 
  if currentstate == 0 : lastsuccess=datetime.datetime.now()
  if currentstate == 0 and currentstate != previousstate and lastreported == 1 : 
    log (datetime.datetime.now().strftime("%Y/%m/%d %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("%Y/%m/%d %H:%M:%S") + "- " + device + " online, tell domoticz it's back")
      if ping_domo_variable == True:
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=1" + "&passcode=" + domoticzpasscode)
      if noonoffevent == 0 :
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=On&level=0" + "&passcode=" + domoticzpasscode)
      else:
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid + "&nvalue=1&svalue=On" + "&passcode=" + domoticzpasscode)
    else:
      log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- " + device + " online, but domoticz already knew")
    lastreported=1
    wait = 0
 
  if currentstate == 1 and currentstate != previousstate :
    log (datetime.datetime.now().strftime("%Y/%m/%d %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("%Y/%m/%d %H:%M:%S") + "- " + device + " offline, tell domoticz it's gone")
      if ping_domo_variable == True:
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=1" + "&passcode=" + domoticzpasscode)
      if noonoffevent == 0 :
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=Off&level=0" + "&passcode=" + domoticzpasscode)
      else:
        domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid + "&nvalue=0&svalue=Off" + "&passcode=" + domoticzpasscode)
    else:
      log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- " + device + " offline, but domoticz already knew")
    lastreported=0
    wait = 0
  
  if syncstate == 1 and currentstate == previousstate :
    if lastreported != domoticzstatus() :
      wait += 1
      if waitcount <= wait :
        if currentstate == 1 :
          log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- " + device + " offline, domoticz state and last reported state are different, time to correct state to offline")
          if ping_domo_variable == True:
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=1" + "&passcode=" + domoticzpasscode)
          if noonoffevent == 0 :          
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=Off&level=0" + "&passcode=" + domoticzpasscode)
          else:
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid + "&nvalue=0&svalue=Off" + "&passcode=" + domoticzpasscode)
          lastreported=0
          wait = 0
        else:
          log (datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "- " + device + " online, domoticz state and last reported state are different, time to correct state to online")
          if ping_domo_variable == True:
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=updateuservariable&vname=Ping_" + device + "&vtype=0&vvalue=1" + "&passcode=" + domoticzpasscode)
          if noonoffevent == 0 :          
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=On&level=0" + "&passcode=" + domoticzpasscode)
          else:
            domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid + "&nvalue=1&svalue=On" + "&passcode=" + domoticzpasscode)
          lastreported=1
          wait = 0

  time.sleep (float(interval))
 
  previousstate=currentstate
  if check_for_instances.lower() == "pid": open(pidfile, 'w').close()

Setup:
- RPi4 - Domo Stable / Aeotec Z-stick7 / PiHole Unbound Gemini
- RPi4 - PiHole / PiVPN Unbound Gemini
- Synology DS923+ / DS218j
- P1 Gas/Power, SmartGateway watermeter
- Fibaro switches, contacts, plugs, smoke/Co2 ect
- rootfs @ USB HDD
User avatar
havnegata
Posts: 114
Joined: Wednesday 10 September 2014 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10162
Location: Norway
Contact:

Re: Improved Presence Detection / Ping Script:

Post by havnegata »

Siewert308SW wrote: Friday 27 October 2017 21:01 @borcon

Offcourse for those who love to ping BT devices.
Your amended script can also be used to ping BT MAC addresses.
I personally use ChopperRob his first script to ping BT devices.

Below your script with just a small edit for BT ping.
Instead of using a IP you have to use the MAC address of BT device.

call the script like this in cron:
*/10 * * * * sudo python /home/pi/domoticz/scripts/python/bt_device_online.py 22:88:72:EE:26:51 13 60 90 1
When you say "Instead of using a IP you have to use the MAC address of BT device", do you then mean in the cron or in the user variable "Ping_YOURIPADDRESS"?

Edit: It's the cron that needs the bluetooth address.
borcon
Posts: 20
Joined: Thursday 05 January 2017 11:15
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Contact:

Re: Improved Presence Detection / Ping Script:

Post by borcon »

Installation instructions added in first post.
lost
Posts: 660
Joined: Thursday 10 November 2016 9:30
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Improved Presence Detection / Ping Script:

Post by lost »

havnegata wrote: Friday 03 November 2017 21:16 When you say "Instead of using a IP you have to use the MAC address of BT device"
Beware that using an IP from an equipment that got it because allowed to connect to your network (using a protected wifi) can be considered trusted. But using only the BT mac, without another check (true pairing, checking other equipment info to make spoofing more difficult...), be aware that you're using some public info (for everyone that can someday listen BT pairing tries in reach of your phone/dongle) to control your alarm system!
User avatar
cobrp
Posts: 6
Joined: Tuesday 02 June 2015 13:40
Target OS: Raspberry Pi / ODroid
Domoticz version: V3.8153
Location: Enschede, the Netherlands
Contact:

Re: Improved Presence Detection / Ping Script:

Post by cobrp »

Did anyone test the stability of the measurements of those presence scripts?
The well know Python script does not always deliver the correct status of my iPhone.
The bash script at https://gist.github.com/kolargol has the same problems, but does a better job.
On my Raspberry i added hping3 to 'wake up' the iPhone with a UDP call over port 5353. That delivers no improvement either
User avatar
Siewert308SW
Posts: 290
Joined: Monday 29 December 2014 15:47
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: The Netherlands
Contact:

Re: Improved Presence Detection / Ping Script:

Post by Siewert308SW »

cobrp wrote: Monday 13 November 2017 15:18 Did anyone test the stability of the measurements of those presence scripts?
The well know Python script does not always deliver the correct status of my iPhone.
The bash script at https://gist.github.com/kolargol has the same problems, but does a better job.
On my Raspberry i added hping3 to 'wake up' the iPhone with a UDP call over port 5353. That delivers no improvement either
Script doesn't have anything to do with your Phone.
It's all about the phone its OS and how it handles its sleep/standby for wireless chipset.
Don't have any experience with apple products but with android devices i can say with ChopperRob his python which this OP scripts is forked off is running for 2 years without issues.
Setup:
- RPi4 - Domo Stable / Aeotec Z-stick7 / PiHole Unbound Gemini
- RPi4 - PiHole / PiVPN Unbound Gemini
- Synology DS923+ / DS218j
- P1 Gas/Power, SmartGateway watermeter
- Fibaro switches, contacts, plugs, smoke/Co2 ect
- rootfs @ USB HDD
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest