Presence detection seems to be a never ending story. This script has proven to be 100% accurate in my home. The script runs continuously and informs Domoticz when a Cell Phone connects or disconnects to your Wifi network on your Ubiquity Access Point that is managed by the software Unifi Controller. Your Unifi Controller must be available 24/7 for this to work. Presence is assumed as long as a cell phone is connected to the wifi so it should be set to always be connected when the wifi can be reached. This script should work even if your phone goes to sleep for saving power.
It's basically a bash scripts running in the background on a linux computer (a Raspberry Pi for example).
It supports multiple Unifi sites handled by a single unifi controller. A Unifi site may have one or many access points assigned to it.
The script will keep the Domoticz virtual devices synchronized with Unifi controller. A connection is normally detected within a minute but a disconnection takes something like 5 minutes. Changing the scripts sleep time from 30 seconds to a lower value seconds doesn't really make much difference so don't.
Prerequisites
You need to have curl installed.
Code: Select all
sudo apt-get update&&sudo apt-get install curl
Create a Domoticz Virtual Switch Device for each person that you want to detect presence for. Name them whatever you like (Maybe something like "MR Green @ Home") and note down the idx of the Domoticz device that you just created. Each person gets an entry in the script similar to this:
Code: Select all
cellPhones["Cell Phone Mr Green"]=123
Single Unifi site
If you have a single site that site's ID is 'default'):
Code: Select all
declare -A sites=([first_site]=default)
If You have multiple Unifi sites you can configure them like in this example:
Code: Select all
declare -A sites=([first_site]=default [second_site]=iw0jsks9)
Something like http://unifi.yourdomain.com/manage/site/abcdef1234 <- this bit
If you are using username and password on your Domoticz host
If you are using username and password on your Domoticz host you can do something similar to this:
Code: Select all
domoticz_ip=username:password@domohostnameorip # Domoticz IP or host name
Code: Select all
mkdir /home/pi/domoticz/scripts/unifi-detect&&cd /home/pi/domoticz/scripts/unifi-detect
Full script name /home/pi/domoticz/scripts/unifi-detect/unifi_detect.sh
Code: Select all
#!/usr/bin/env bash
SCRIPT_VERSION=1.0.1
echo Running `basename "$0"` $SCRIPT_VERSION
# We want a single instance of this script
status=`ps -efww | grep -w "[u]nifi_detect.sh" | awk -vpid=$$ '$2 != pid { print $2 }'`
numProcs=( $status )
if [ ${#numProcs[@]} -gt 2 ]; then
printf "[`date`] : unifi_detect.sh:\n\nEverything is fine. The script is already running.\nNo need to do start another instance\n\n$status"
exit 1;
fi
declare -A sites
declare -A cellPhones
########################################################
# CONFIG START Do not make any changes above this line #
########################################################
unifi_username=roger
unifi_password=jyhgJbjuyJyvjVT65kjh
unifi_controller=https://192.168.1.112:8443
domoticz_ip=192.168.1.14 # Domoticz IP or host name
domoticz_port=8080
# Most Unifi installations have a single Unifi site.
# A single Unifi site can he configured to have many access points.
# Each Unifi site has a name and an ID. The first defined Unifi site always has the ID "default"
# (Site name is visible in the Unifi GUI at top right corner)
# (ID is visible in the Unifi GUI URL, it's 8 random characters)
sites["My Home"]=default # The default Unifi site
#sites["Another Site"]=iw0jjht6
# Phone devices, e.g. persons that you wish to detect presence for
# The name can be anuthing that you find descriptive.
# The idx (numeric) is the Domoticz virtual switch device idx that you wish to switch on/off
cellPhones["Person A"]=375
cellPhones["Person B"]=627
cellPhones["Person C"]=628
########################################################
# CONFIG END Do not make any changes below this line. #
########################################################
cookie=/tmp/unifi_cookie
declare -A lastStates
curl_cmd="curl --silent --cookie ${cookie} --cookie-jar ${cookie} --insecure "
unifi_login() {
# authenticate against unifi controller
${curl_cmd} --output /dev/null -H "Content-Type: application/json" -X POST -d "{\"password\":\"$unifi_password\",\"username\":\"$unifi_username\"}" $unifi_controller/api/login
}
unifi_logout() {
# logout
${curl_cmd} $unifi_controller/logout
}
switchDevice() {
#echo Checking idx $1 so that it is $2
domoState=$(curl --silent "http://$domoticz_ip:$domoticz_port/json.htm?type=devices&rid=$1")
#echo "$domoState"
if echo "$domoState" | grep -q "\"Status\" : \"On\""; then
oldState=On;
else
oldState=Off;
fi
if [ "$oldState" != "$2" ]; then
echo Switching idx $1 state to $2
curl --silent --output /dev/null "http://$domoticz_ip:$domoticz_port/json.htm?type=command¶m=switchlight&idx=$1&switchcmd=$2"
fi
}
# stat/sta
unifi_list_sta() {
for i in "${!sites[@]}"; do
${curl_cmd} --write-out \\n%{http_code} --data "json={}" $unifi_controller/api/s/${sites[$i]}/stat/sta
done
}
unifi_login
loopCounter=999999
while [ 1 -lt 2 ]; do
((loopCounter++))
if [ "$loopCounter" -gt 240 ]; then
#echo "Resetting the counter"
loopCounter=1
for i in "${!lastStates[@]}"; do
lastStates[$i]="Unknown"
done
fi
#put unifi_list_sta output in variable
var=$(unifi_list_sta)
#echo "$var"
resultCode="${var##*$'\n'}"
for i in "${!cellPhones[@]}"; do
if echo "$var" | grep -q "$i"; then
newState="On";
else
newState="Off";
fi
if [ "$newState" != "${lastStates[$i]}" ]; then
lastStates[$i]="$newState"
switchDevice "${cellPhones[$i]}" "$newState";
fi
done
if [ "$resultCode" != "200" ]; then
echo "Exiting with a result code of : $resultCode"
exit 1
fi
#echo "Let's have some sleep..."
sleep 30
done
unifi_logout
Code: Select all
sudo chmod 755 /home/pi/domoticz/scripts/unifi-detect/unifi_detect.sh
Code: Select all
/home/pi/domoticz/scripts/unifi-detect/unifi_detect.sh
Code: Select all
*/5 * * * * /home/pi/domoticz/scripts/unifi-detect/unifi_detect.sh
Trouble shooting
To see the result fetched from the Unifi controller you can temporary remove the leading # from the following line:
Code: Select all
#echo "$var"
If you have any questions or need help you can post in this thread. Please don't send PMs to me.