WiFi devices presence check

Moderator: leecollings

Post Reply
Jan
Posts: 4
Joined: Wednesday 05 February 2014 7:18
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

WiFi devices presence check

Post by Jan »

This weekend I was busy with my DD-WRT WiFi routers (TP Link and WRT 54G router) and Raspberry Pi to determine if somebody is at home (detecting WiFi of Cell Phones). See also http://www.domoticz.com/forum/viewtopic ... snmp#p6999. All credits are for SweetPants (http://www.domoticz.com/forum/memberlis ... ofile&u=96)! I have only changed the python file to be able to read a json file with all phones, tables, etc.

I made a bash file which runs every 1 minute from a cron job (sudo crontab -e):
* * * * * /home/pi/script/wifi_presence_check.sh

The bash file looks like (wifi_presence_check.sh):

Code: Select all

#!/bin/bash
#
#$HOME/signalplus.py -i <ip_router> -c <community_string> -f  <JSON_file_with_MAC_addresses> --verbose >> /tmp/wifi_presence_check.log &

sudo python /home/pi/script/wifi_presence_check.py -i 192.168.178.254 -c public -f /home/pi/script/wifi_devices.json --verbose >> /tmp/wifi_presence_check.log &
My json file looks like (wifi_devices.json):

Code: Select all

{

	"83:63:07:05:38:29": {
		"Vendor": "BlackBerry",
		"Type": "Phone",
		"Model": "Torch",
		"Owner": "Pietje",
		"Idx": 83
	},

.......

	"F8:FA:51:67:C2:91": {
		"Vendor": "Apple",
		"Type": "Tablet",
		"Model": "iPad Mini",
		"Owner": "Frits",
		"Idx": 89
	}

}
My python script looks like (wifi_presence_check.py):

Code: Select all

#!/usr/bin/python
import sys
import argparse
import netsnmp
import json
import httplib
from datetime import datetime
from pprint import pprint

__author__ = 'Harry Soeterbroek & Jan N'
__version__ = '0.2'

def cli_options():
	cli_args = {}
	cli_args['ipaddress'] = '192.168.178.1' 
	cli_args['community'] = 'public'
	cli_args['version'] = 2
	cli_args['secname'] = None
	cli_args['seclevel'] = 'AuthNoPriv'
	cli_args['authpassword'] = None
	cli_args['authprotocol'] = 'MD5'
	cli_args['privpassword'] = None
	cli_args['privprotocol'] = 'DES'
	cli_args['port'] = 161
	cli_args['jsonmacaddressfile'] = None
	cli_args['verbose'] = False

	# Parse the CLI
	parser = argparse.ArgumentParser()
	parser.add_argument('-v', '--version', help='SNMP version', type=int )
	parser.add_argument('-c', '--community', help='SNMPv1/2 community string')
	parser.add_argument('-i', '--ipaddress', help='IP address of device to query', required=True)
	parser.add_argument('-u', '--secname', help='SNMPv3 secname')
	parser.add_argument('-l', '--seclevel', help='SNMPv3 security level (NoAuthNoPriv, AuthNoPriv, AuthPriv)')
	parser.add_argument('-A', '--authpassword', help='SNMPv3 authpassword')
	parser.add_argument('-a', '--authprotocol', help='SNMPv3 authprotocol (MD5, SHA)')
	parser.add_argument('-X', '--privpassword', help='SNMPv3 privpassword')
	parser.add_argument('-x', '--privprotocol', help='SNMPv3 privprotocol (DES, 3DES, AES128)')
	parser.add_argument('-p', '--port', help='SNMP UDP port', type=int)
	parser.add_argument('-f', '--jsonmacaddressfile', help='JSON File with WiFi device MAC addresses', required=True)
	parser.add_argument('--verbose', help='Verbose mode', action='store_true', default=False)

	# Parse arguments and die if error
	try:
		args = parser.parse_args()
	except Exception:
		sys.exit(2)

	# Assign and verify SNMP arguments
	if args.version:
		cli_args['version'] = args.version
	if args.community:
		cli_args['community'] = args.community
	if args.ipaddress:
		cli_args['ipaddress'] = args.ipaddress
	if (cli_args['version'] != 1) and (cli_args['version'] != 2) and (cli_args['version'] != 3):
		print 'ERROR: Only SNMPv2 and SNMPv3 are supported'
		sys.exit(2)
	if args.secname:
		cli_args['secname'] = args.secname
	if args.secname:
		cli_args['seclevel'] = args.seclevel
	if (not cli_args['secname']) and (cli_args['version'] == 3):
		print '{0} ERROR: SNMPv3 must specify a secname'.format(date_time())
		sys.exit(2)
	if args.authpassword:
		cli_args['authpassword'] = args.authpassword
	if args.authprotocol:
		cli_args['authprotocol'] = args.authprotocol.upper()
	if args.privpassword:
		cli_args['privpassword'] = args.privpassword
	if args.privprotocol:
		cli_args['privprotocol'] = args.privprotocol.upper()
	if args.port:
		cli_args['port'] = args.port 
	if args.jsonmacaddressfile:
		cli_args['jsonmacaddressfile'] = args.jsonmacaddressfile
	if (cli_args['version']!= 3) and (not cli_args['community']):
		print '{0} ERROR: SNMP community string not defined'.format(date_time())
		sys.exit(2)
	if args.verbose:
		cli_args['verbose'] = args.verbose 

	return (cli_args)


def is_number(val):
	try:
		float(val)
		return True
	except ValueError:
		return False


def snmp_walk(cli_args, oid):
	return_results = {}
	session = False
	results_objs = False

	try:
		session = netsnmp.Session(
		DestHost=cli_args['ipaddress'],Version=cli_args['version'], Community=cli_args['community'],
		SecLevel=cli_args['seclevel'], AuthProto=cli_args['authprotocol'], AuthPass=cli_args['authpassword'],
		PrivProto=cli_args['privprotocol'], PrivPass=cli_args['privpassword'], SecName=cli_args['secname'], UseNumeric=True)

		results_objs = netsnmp.VarList(netsnmp.Varbind(oid)) 
		session.walk(results_objs)
	except Exception as e:
		print "{0} ERROR: Occurred during SNMPget for OID {1} from {2}: ({3})".format(date_time(), oid, cli_args['ipaddress'], e)
		sys.exit(2)

	# Crash on error
	if (session.ErrorStr):
		print "{0} ERROR: Occurred during SNMPget for OID {1} from {2}: ({3}) ErrorNum: {4}, ErrorInd: {5}".format(date_time(), oid, cli_args['ipaddress'], session.ErrorStr, session.ErrorNum, session.ErrorInd)
		sys.exit(2)

	# Construct the results to return
	for result in results_objs:
		if is_number(result.val):
			return_results[('%s.%s') % (result.tag, result.iid)] = ( float(result.val))
		else:
			return_results[('%s.%s') % (result.tag, result.iid)] = ( result.val)

	# Print each MAC address in verbose mode
	if cli_args['verbose']:
		print "{0} DEBUG: MAC address presence:".format(date_time())
		for oid, mac in return_results.iteritems():
			mac = bin_to_mac(mac).upper() # Convert binary MAC to HEX
			print "{0}".format(mac)

	return return_results 


def date_time():
	return datetime.now().strftime('%Y/%m/%d %H:%M:%S')


def bin_to_mac(octet):
	return ":".join([x.encode("hex") for x in list(octet)])


def mac_table(cli_parms, oid):
	(mac_results) = snmp_walk(cli_parms, oid)

	return mac_results

	
def mac_in_table(searched_mac, mac_results, oid):
	mac = searched_mac
	# Loop through every MAC address found
	for oid, mac in mac_results.iteritems():
		mac = bin_to_mac(mac).upper() # Convert binary MAC to HEX
		if mac == searched_mac:
			return True

	return False


# This class is derived from Pymoticz, modified to use httplib
class Domoticz:
	def __init__(self, domoticz_host='127.0.0.1:8080'): # Default on localhost
		self.host = domoticz_host


	def _request(self, url):
		(ip, port) = self.host.split(":")
		http = httplib.HTTPConnection(ip, port, timeout=2)
		http.request("GET", url)
		result = http.getresponse()

		if (result.status != 200):
			raise Exception

		http.close()
		return json.loads(result.read())


	def list(self):
		url='/json.htm?type=devices&used=true'
		return self._request(url)

	def turn_on(self, _id):
		url='/json.htm?type=command&param=switchlight&idx=%s&switchcmd=On' % (_id)
		return self._request(url) 

	def turn_off(self, _id):
		url='/json.htm?type=command&param=switchlight&idx=%s&switchcmd=Off' % (_id)
		return self._request(url)

	def turn_on_if_off(self, _id):
		status=False
		if (self.get_switch_status(_id) == "Off"):
			self.turn_on(_id)
			status=True
		return status

	def turn_off_if_on(self, _id):
		status=False
		if (self.get_switch_status(_id) == "On"):
			self.turn_off(_id)
			status=True
		return status

	def turn_on_off(self, _id, _state):
		url='/json.htm?type=command&param=switchlight&idx=%s&switchcmd=%s' % (_id, _state)
		return self._request(url)

	def get_switch_status(self, _id):
		try:
			device = self.get_device(_id)
		except:
			return None

		return device['Status']

	def get_device(self, _id):
		url='/json.htm?type=devices&rid=%s' % (_id)
		try:
			device = self._request(url)
		except:
			return None

		return device['result'][0]


def main():
	# Parse the CLI options
	(cli_parms) = cli_options()

	# Read JSON file
	try:
		json_data = open(cli_parms['jsonmacaddressfile'])
		data = json.load(json_data)
		json_data.close()
	except Exception as e:
		print "{0} ERROR: Occurred during reading file {1}: ({2})".format(date_time(), cli_parms['jsonmacaddressfile'], e)
		sys.exit(2)

	(found_macs) = mac_table(cli_parms, '.1.3.6.1.4.1.2021.255.3.54.1.3.32.1.4')

	for key, value in data.items():

		# Switch by Index (idx)
		switch_idx = value["Idx"]

		# Get instance of Domoticz class optional ip:port, default = 127.0.0.1:8080
		d = Domoticz()

		# Get Name of switch from Domoticz
		switch_name = d.get_device(switch_idx)['Name']

		if mac_in_table(key, found_macs, '.1.3.6.1.4.1.2021.255.3.54.1.3.32.1.4'):
			if d.turn_on_if_off(switch_idx) and cli_parms['verbose']: # Turn switch On only if Off
				print "{0} DEBUG: Switching {1}: {2}".format(date_time(), "On", switch_name)
		else:
			if d.turn_off_if_on(switch_idx) and cli_parms['verbose']:# Turn switch Off only if On
				print "{0} DEBUG: Switching {1}: {2}".format(date_time(), "Off", switch_name)

if __name__ == "__main__":
	main()
PS. SNMP must be enabled in your router!
My hardware:
- Raspberry Pi
- Rfxtrx433 transceiver
- RaZberry
- Nuon Smart Plug 6 (2x)
- Nuon Smart Plug (5x)
- Fibaro Universal Sensor
- Fibaro Smoke Sensor
- Aeon Door Sensor
- Bluetooth dongle
xKingx
Posts: 15
Joined: Tuesday 03 June 2014 11:23
Target OS: Raspberry Pi / ODroid
Domoticz version: 2022.1
Location: Holland
Contact:

Re: WiFi devices presence check

Post by xKingx »

Hello,

I found the above quite interesting and have been working on and off to make some additions to suit me. The result I put on github should others want to use it. I know there are some issues and I might not address them, but it might give others some ideas.

Below contents of the README, should explain most.

THANKS AND ACKNOWLEDGEMENT
Thanks and credits go out to the below people on the Domoticz Forum (http://www.domoticz.com/forum/index.php), from which I generously borrowed most of their work: Purpose
I wanted a way to let Domoticz know when a person in my household (defined by a mobile device) was inside or close by and trigger switches in Domoticz based on that. I found a couple of script doing this using SNMP on the Domoticz forums. However I have a couple of routers I need to look at as devices can switch between them and I do not want switches to go on and of each time. So I combined what suited me best from various scripts, added some additions of my own and wrote a little documentation.

So now this is a script fed by 2 input files (for router and mobile device details) running as a makeshift daemon checking SNMP details every x seconds.

VERSIONING

Code: Select all

Script : check_device_online.py
Initial version : SweetPants & Jan N
Version : 1.10.2
Date : 23-12-2014
Author : xKingx

Version       Date            Author    Major changes
1.0           31-10-2014      xKingx    Added sleep loop | Added sleep time input option
1.1           04-11-2014      xKingx    Added Domoticz host as an optional variable
1.2           05-11-2014      xKingx    Added option to device json file to turn on optional switch
1.3           06-11-2014      xKingx    Added option to search routers based on JSON input and removed ip option from command line input
1.4           19-11-2014      xKingx    Added community string to JSON SNMP device list and use it to read out router
1.5           20-11-2014      xKingx    Moved some stuff to functions for some more flexibility
1.6           20-11-2014      xKingx    Moved SNMP key variable to SNMP Router JSON file
1.7           20-11-2014      xKingx    Bug fixes
1.8           20-11-2014      xKingx    Prevent Idx_opt option in mobile JSON file from being mandatory, can be empty string
1.8.1         26-11-2014      xKingx    Temporary version with initial code for location detection
1.9           12-12-2014      xKingx    Location detection enabled with switching of "dummy" devices added
1.9.1         15-12-2014      xKingx    Fixed location detection switching as it did not work ok
1.10          16-12-2014      xKingx    Ignoring switch location and added input checks on router json file
1.10.1        19-12-2014      xKingx    Added some json input checks and cleaned up some code
1.10.2        23-12-2014      xKingx    Added some more json input checks and updated README
TODO
  • * Add option to ignore location switching if not used
    * Build in check for community string in SNMP version <3
    * General input validation on parameters received from command line and JSON files, router file done in v1.10
    * Look into way results of SNMP walk are gathered as I put a dirty counter hack in
    * Look at way to prevent devices that reconnect from triggering presence reporting
    * Add MAC intruder detections, i.e. a MAC not known in JSON input triggers Domoticz switch
SETUP
* Disclaimer
  • - I have this script running for a couple of weeks already without issues. That being said I cannot guarentee that it will work in other situations and setups. Please take that into account when attempting to use this.
    - I am fine for anyone to use or modify this script as long as no money is made and the creators are mentioned.
* Pre-requisits
  • - This script is not compatible with python 3 (yet) and is tested on python 2.7
    - This scripts assumes you have a SNMP capable [dd-wrt router](http://dd-wrt.com/). It's tested with various dd-wrt versions on various routers. To turn it on in the dd-wrt GUI go to *"services" tab, enable SNMP, set it up like you want and hit "Save" and "Apply Settings"*
    - To run on RPI with standard Domoticz image add these packages from a shell prompt : *sudo apt-get install python snmp libsnmp-python*
* Configuration
- check_device_online.py takes the following parameters:

Code: Select all

   [-h]                         -> Display help
   [-v VERSION]                 -> SNMP version, default 2 
   [-c COMMUNITY]               -> SNMP v1/2 community string, default public 
   [-u SECNAME]                 -> SNMP v3 security name, default none 
   [-l SECLEVEL]                -> SNMP v3 security level, default AuthNoPriv, options NoAuthNoPriv, AuthNoPriv, AuthPriv
   [-A AUTHPASSWORD]            -> SNMP v3 authentication password, default None
   [-a AUTHPROTOCOL]            -> SNMP v3 authentication protocol, default MD5, options MD5, SHA  
   [-X PRIVPASSWORD]            -> SNMP v3 private password, default None 
   [-x PRIVPROTOCOL]            -> SNMP v3 private protocol, default DES, options DES, 3DES, AES128 
   [-p PORT]                    -> SNMP UDP port, default 161 
   [-d DOMOTICZHOST]            -> ip and port of your Domoticz instalation
   -f JSONMACADDRESSFILE        -> Full path to file with mobile device information
   -r JSONSNMPROUTERSFILE       -> Full path to file with router information
   -s SLEEPTIME                 -> Amount of time in seconds between SNMP checks
   [--verbose]                  -> Output verbose information
  
- snmp_routers.json follows this setup. Non mandatory parameters could be removed if required.

Code: Select all

   ipaddress                    -> IP address of your router (mandatory, it's the key of the router to check precense against)
   "Vendor"                     -> Router vendor - not used a.t.m. / can be removed if desired
   "Model"                      -> Router model - not used a.t.m. / can be removed if desired
   "Purpose"                    -> Router purpose - not used a.t.m. / can be removed if desired
   "Location"                   -> Router location - used to give location a meaningfull name, will be set to default if removed and not switched.
   "LocationIdx"                -> Router location Domoticz switch id - used to turn on/off location (dummy) switch in Domoticz, can be removed if not used 
   "CommunityString"            -> Router SNMP communitystring (mandatory, script will exit without it)
   "RequestString"              -> SNMP query string for value to be returned from router (mandatory, script will exit without it)
  
- wifi_devices.json follows this setup. Non mandatory parameters could be removed if required.

Code: Select all

    mobile mac address          -> MAC address of your mobile device (mandatory)
    "Vendor"                    -> Mobile device vendor - not used a.t.m. / can be removed if desired
    "Type"                      -> Mobile device type - not used a.t.m. / can be removed if desired
    "Model"                     -> Mobile device model - not used a.t.m. / can be removed if desired
    "Owner"                     -> Mobile device owner - not used a.t.m. / can be removed if desired
    "Idx"                       -> Domoticz switch to turn on and off (mandatory, script will exit without it)
    "Idx_opt"                   -> Additional Domoticz switch to turn on and off, can be removed if desired
EXECUTION
This script is scheduled through a crontab entry (if preferred through a wrapper script). My crontab entry for a script looks like this:

Code: Select all

* * * * * /home/pi/domoticz/scripts/wifi_presence_check.sh
The contents of that script for me are:

Code: Select all

python /home/pi/domoticz/scripts/wifi_presence_check.py -d <ip>:<port> -s 20 -f /home/pi/domoticz/scripts/wifi_devices.json -r /home/pi/domoticz/scripts/snmp_routers.json | tee -a /home/pi/domoticz/log/wifi_presence_check.log


Individual files on GitHub which will be updated when changes are made here: Have fun!
Raspberry Pi running Domoticz image
Animeimp
Posts: 2
Joined: Tuesday 03 February 2015 1:42
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: WiFi devices presence check

Post by Animeimp »

What goes in this entry of the config json?

"RequestString" -> SNMP query string for value to be returned from router (mandatory, script will exit without it)

From looking at the script, it appears just to be doing a snmp walk, so there should be no particular requeststring.
Domotiz 2.2276/Synology DS512+/Aeon Z Wave/Hue Lights
xKingx
Posts: 15
Joined: Tuesday 03 June 2014 11:23
Target OS: Raspberry Pi / ODroid
Domoticz version: 2022.1
Location: Holland
Contact:

Re: WiFi devices presence check

Post by xKingx »

Hi,

In the SNMP walk function the request string, be it somewhat tricky, is put in the "oid" value:
...
oid = keys[2]
...

This is used to get the required values from the router:
...
results_objs = netsnmp.VarList(netsnmp.Varbind(oid))
session.walk(results_objs)
...

From http://www.dd-wrt.com/wiki/index.php/Si ... t_Protocol this request string returns:
.1.3.6.1.4.1.2021.255.3.54.1.3.32.1.4.1 Associated MAC text 00:ff:as:dd:44:55

So it is used to query the specific MAC addresses associated with the router.


xKingx
Raspberry Pi running Domoticz image
Timple
Posts: 5
Joined: Tuesday 20 January 2015 8:05
Target OS: Linux
Domoticz version:
Contact:

Re: WiFi devices presence check

Post by Timple »

Cool, I am going to look into this since I also have a dd-wrt router.

Are there any advantages compared to the ip-check done by ChopperRob?

Maybe more robust, less depended on phone state?

Would be nice to state them in the readme so people know why they should put in the effort ;)
pj-r
Posts: 140
Joined: Wednesday 17 December 2014 17:30
Target OS: Linux
Domoticz version: V3.8650
Location: Jyväskylä, Finland
Contact:

Re: WiFi devices presence check

Post by pj-r »

What I did with my dd-wrt router:
1. automatic login with ssh
2. from python script:

Code: Select all

currentstate = subprocess.call('ssh [email protected] -i /home/user/.ssh/id_rsa "wl assoclist" | sed -e \'s/assoclist[[:space:]]//g\' | grep -q '+ device + ' > /dev/null', shell=True)
192.168.1.1 is my dd-wrt router
with wl assoclist I can get list of mac addressess of devices online on wlan.

Its based on the script on wiki. I just replaced the line calling ping and instead of ip i'm giving mac address as parameter.
LXC(x64 Ubuntu Xenial), RFXtrx433E, MySensors
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: WiFi devices presence check

Post by ThinkPad »

That's nice.

Code: Select all

wl assoclist
also seems to work on my WRT54GL with Tomato firmware.
Would you mind sharing your whole Python script?

Is the behaviour of that output different than pinging a device?
I am not active on this forum anymore.
pj-r
Posts: 140
Joined: Wednesday 17 December 2014 17:30
Target OS: Linux
Domoticz version: V3.8650
Location: Jyväskylä, Finland
Contact:

Re: WiFi devices presence check

Post by pj-r »

ThinkPad wrote:That's nice.

Code: Select all

wl assoclist
also seems to work on my WRT54GL with Tomato firmware.
Would you mind sharing your whole Python script?

Is the behaviour of that output different than pinging a device?
Its exactly the same script what is in the presence detection wiki page.

I just replaced one line:

Code: Select all

...
currentstate = subprocess.call('ping -q -c1 -W 1 '+ device + ' > /dev/null', shell=True)
...
with this:

Code: Select all

...
currentstate = subprocess.call('ssh [email protected] -i /home/user/.ssh/id_rsa "wl assoclist" | sed -e \'s/assoclist[[:space:]]//g\' | grep -q '+ device + ' > /dev/null', shell=True)
...
and in cron I have one line per device I want to monitor:

Code: Select all

0 * * * * /home/user/domoticz/scripts/lua/check_device_online.py 01:23:45:67:89:0A 21 10 120
LXC(x64 Ubuntu Xenial), RFXtrx433E, MySensors
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: WiFi devices presence check

Post by ThinkPad »

Nice, thanks for explaining :)
I am not active on this forum anymore.
Bohatyaor
Posts: 1
Joined: Tuesday 26 April 2016 9:06
Target OS: Linux
Domoticz version:
Contact:

Re: WiFi devices presence check

Post by Bohatyaor »

Build in check for community string in SNMP version <3
* General input validation on parameters received from command line and JSON files, router file done in v1.10
* Look into way results of SNMP walk are gathered as I put a dirty counter hack in
* Look at way to prevent devices that reconnect from triggering presence reporting????
User avatar
thecosmicgate
Posts: 188
Joined: Monday 06 April 2015 14:37
Target OS: Linux
Domoticz version: newest
Location: The Netherlands / Hoeven
Contact:

Re: WiFi devices presence check

Post by thecosmicgate »

Trying to get the chopperbob script running on a https (ssl)

Code: Select all

#!/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="[i]https server[/i]"
domoticzusername = "[i]pwd[/i]"
domoticzpassword = "[i]login0[/i]"
 
# 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 = 'https://'+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 and "Lighting" in json_object["result"][i]["Type"] :
        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)
 
  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("https://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=On&level=0")
    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("https://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=Off&level=0")
    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()  
Also with some SSL cert but didn't get it to work, are there more people with this config , and get it working ?

Also what's happend with chopperbob his site ?
It's nice to be important, but it's more important to be nice
Scooter ;)
pj-r
Posts: 140
Joined: Wednesday 17 December 2014 17:30
Target OS: Linux
Domoticz version: V3.8650
Location: Jyväskylä, Finland
Contact:

Re: WiFi devices presence check

Post by pj-r »

I'm currently using this with my dd-wrt router:

Code: Select all

currentstate = subprocess.call('curl -u user:password http://192.168.1.1/Status_Lan.live.asp | awk -F \'arp_table:: \' \'{print $2}\' | awk -F \'}\' \'{print $1}\' | grep -i -q ' + device + ' > /dev/null', shell=True)
Its using http ui since using ssh was causing much overhead(cpu usage). Works well at least with: DD-WRT v3.0-r29059 std (02/09/16)
LXC(x64 Ubuntu Xenial), RFXtrx433E, MySensors
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests