问题
Hi I have made an automatic light switch program destined for my pi, it tracks if my phone is on wifi network it works but its not very fast. If i speed it up I either receive lots of false positives or doesnt work I have found and only changed a tiny bit of code from other examples online. I'm still learning.
so I've got two lots of code one bash and one python. python uses arp-scan and bash uses ip neighbor and ping with seem to be more reliable so can someone help me mash the bash code into python and make it use {arp-scan, ip neighbor, ping and maybe bluetooth as well
I would like to add some settings like
- ensure the lights dont get turned on in day time hours
- somehow track the gpio high low toggle in a better way
- adding bluetooth scan that actually work when android dev is sleeping (screen off)
at the moment i have it running on the pi as a web site for testing here is a screenshot of my pi site
python code example
#!/usr/bin/python3
import RPi.GPIO as GPIO
import subprocess
from time import sleep
is_home = False
home_run_count = 0
out_run_count = 0
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
if __name__ == '__main__':
while True:
p = subprocess.Popen("arp-scan -l -r 6 | grep MAC:MAC:MAC",stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
p_status = p.wait()
if output:
#print("Android device is connected to your network!")
is_home = True
if p.returncode != 0:
#print("The device is not present!")
is_home = False
#home_run_count = 0
#out_run_count -= 1
if is_home is True and home_run_count < 1:
#print("lights on!")
#GPIO.setmode(GPIO.BCM)
#GPIO.setup(17, GPIO.OUT)
GPIO.output(17, True)
sleep(0.5);
GPIO.output(17, False)
home_run_count += 1
out_run_count = 0
is_home = True
if is_home is False and out_run_count < 1:
#print("lights off!")
#GPIO.setmode(GPIO.BCM)
#GPIO.setup(17, GPIO.OUT)
GPIO.output(17, True)
sleep(0.5);
GPIO.output(17, False)
out_run_count += 1
home_run_count = 0
is_home = False
enter code here
Bash script code
#!/bin/bash
# A script to do something when Phone returns Home.
mac="some mac addy" # Your phone mac address
ip_addr="" # Leave blank or ip for test
network="some ip addy" # Your network (Class C only)
range="90 100" # ip address possible range
pgm() {
echo "switching lights "
echo "1" > /sys/class/gpio/gpio17/value
sleep 0.5s
echo "0" > /sys/class/gpio/gpio17/value
}
#-----Rpi-Mod----
echo "17" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio17/direction
#-----End of Rpi mod first section-------
start=$(echo "$range" | cut -d " " -f1)
stop=$(echo "$range" | cut -d " " -f2)
network=$(echo "$network" | cut -d. -f1-3)
echo "Start $(date)"
while [ 1 ]; do
cnt=0
fail=0
[ "$ip_addr" ] || while [ ! "$ip_addr" ]; do
for x in $(seq "$start" "$stop"); do
(junk=$(ping -c1 -W1 "$network"."$x") & )
wait
done
sleep 8
ip_addr=$(ip neighbor | grep "$mac" | cut -d " " -f1)
((cnt++))
if (( $cnt > 15 )); then
cnt=0
echo "--- Phone not Home $(date)"
#sleep 300 # 5 minutes
fi
if [ "$ip_addr" ]; then
echo "--- Phone is Home, Count = $cnt, Date = $(date)"
echo "Phone ip = $ip_addr mac = $mac"
fi
done
while [ "$ip_addr" ]; do
junk="$(ping -c1 -W1 $ip_addr)"
sleep 8
home_nw="$(ip neighbor | grep $ip_addr | cut -d ' ' -f 1,5,6)"
echo "$home_nw - $(date)"
is_home=$(echo "$home_nw" | cut -d " " -f3)
if [ "$is_home" == "REACHABLE" ] && (( "$fail" >= 3 )); then
echo "--- Phone returned Home - $(date)"
pgm
fi
[ "$is_home" == "REACHABLE" ] && fail=0
mac_stat=$(echo "$home_nw" | cut -d " " -f2)
if [ "$mac_stat" == "FAILED" ]; then
(( "$fail" < 10 )) && ((fail++))
ip_test="$(ip neighbor | grep $mac | cut -d ' ' -f1)"
if [ "$ip_test" ]; then
[ "$ip_test" == "$ip_addr" ] || ip_addr=""
fi
if (( "$fail" == 3 )); then
echo "--- Phone not at Home $(date)"
pgm
fi
else
if [ "$mac_stat" != "$mac" ]; then
ip_addr=""
fi
fi
#sleep 300 # 5 minutes
done
done
I don't know enough to implement my changes but still learning so would appreciate some woking cot to try and in the process learn.
------------------------------------------------------ update -------------------------------------------------------------------
I tried to put code in the comment but it didn't work. I've sort of managed to get what I wanted. I modified the python script to call a new script (see below) because I was unable to get popen to run my function maybe it needs to be a class or clash, I'm open to suggestions.
def present():
with urllib.request.urlopen("http://blah.ip.blah/some.json") as url:
sleep(0.5);
data = json.loads(url.read().decode())
#print(data)
'MAC:MAC:MAC:' in data
So because I could not make the rest of the logic work i just stuck it in a new file like this
#!/usr/bin/python3
import urllib.request, json
from time import sleep
import os
try:
with urllib.request.urlopen("http://blah.ip.blah/some.json") as url:
sleep(0.5);
data = json.loads(url.read().decode())
#print(data)
'MAC:MAC:MAC:' in data
except KeyboardInterrupt:
os._exit(1)
but would love to combine it with the main light script as a function. why does this not work ?
(output, err) = ( present() )
p_status = ( present() )
----------------------------------------------------------- end of update one -----------------------------------------------
I had some trouble getting the python loop to keep running when called from the site but it was an silly incorrect path issue, that's why I want to have it all on one file
----------------------------------------------------------- end of update two ---------------------------------------------
I've asked a similar question if anyone is interested
