Page 1 of 3

Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Friday 01 September 2017 12:07
by BakSeeDaa
Based on a script originally published by @salvation in this thread, I made this script and I though and I like to share them here in case it can help someone with similar needs.

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
Detection configuring
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
Where 123 is the Domoticz device idx.

Single Unifi site
If you have a single site that site's ID is 'default'):

Code: Select all

declare -A sites=([first_site]=default)
Multiple Unifi sites
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)
When using multiple sites, you can find the site IDs in the unifi controller Web GUI. Your browser's address bar will show it when you're looking at whichever site you're interested in.
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
Create the script directory and put the script in there

Code: Select all

mkdir /home/pi/domoticz/scripts/unifi-detect&&cd /home/pi/domoticz/scripts/unifi-detect
Create the script unifi_detect.sh and customize it using your favorite editor, (e.g. vi)

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&param=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
Set script permissions

Code: Select all

sudo chmod 755 /home/pi/domoticz/scripts/unifi-detect/unifi_detect.sh
Now try the script manually first. Issue at the command prompt:

Code: Select all

/home/pi/domoticz/scripts/unifi-detect/unifi_detect.sh
When things seems to work fine, put this in crontab:

Code: Select all

*/5 * * * * /home/pi/domoticz/scripts/unifi-detect/unifi_detect.sh
Putting the script in the crontab works like a "watch dog" so that there will always be one instance of the script running. That is, it will try to start the script every 5 minutes but the script will detect if there is another instance running and if so it will exit immediately.

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"
Support
If you have any questions or need help you can post in this thread. Please don't send PMs to me.

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Friday 01 September 2017 17:16
by Luigi87
Hi, found the reason for the "Exiting with a result code of : 000" error.

you are missing a / in the url to the unifi site in the script.

Code: Select all

https:/UNIFIIP:8443
must be:

Code: Select all

https://UNIFIIP:8443
Right?

Now the script work with me except the script keeps running:

Code: Select all

pi@raspberrypi:~ $ /home/pi/scripts/unifi-detect/unifi_detect.sh
[Fri  1 Sep 17:55:34 CEST 2017] : unifi_detect.sh : Process is already running:                                                                                                                             17828
17829
30124
So the crontab could not start the script again after 5 minuts

After killing the 2 running scripts i started the script again and is seems to keep running.

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Friday 01 September 2017 19:19
by BakSeeDaa
Luigi87 wrote: Friday 01 September 2017 17:16 Hi, found the reason for the "Exiting with a result code of : 000" error.

you are missing a / in the url to the unifi site in the script.

Code: Select all

https:/UNIFIIP:8443
must be:

Code: Select all

https://UNIFIIP:8443
Right?

Now the script work with me except the script keeps running:

Code: Select all

pi@raspberrypi:~ $ /home/pi/scripts/unifi-detect/unifi_detect.sh
[Fri  1 Sep 17:55:34 CEST 2017] : unifi_detect.sh : Process is already running:                                                                                                                             17828
17829
30124
So the crontab could not start the script again after 5 minuts

After killing the 2 running scripts i started the script again and is seems to keep running.
That's perfect. It's supposed to run continuously. It's in the crontab just in case it has stopped running for some reason. Then it will start new. So it seems to work great!

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Friday 01 September 2017 19:31
by Luigi87
Oke, but the virtualswitch has to be update every 5 minuts right?
The switch has only updated when i manualy run the script.

Edit:
Ah oke I understand, I think.
It looks like it’s working now. I thought the switch had to be updated every 5 minutes, but I switched off my phone of the Wi-Fi and now the switch is set to "off" so it works :D

kick-ass :D

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Friday 01 September 2017 19:35
by BakSeeDaa
It will only update if the script detects a state change in unifi. Otherwise there is no need to update.

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Friday 01 September 2017 19:37
by Luigi87
Oke, sorry my bad!
it's working properly now. Thanks for the support :P , now i have to add my girlfrends phone and change some other logic. :D

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Friday 01 September 2017 19:41
by BakSeeDaa
I'm so happy that it works for you. I hope that it will suit your needs. Cheers!

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Saturday 02 September 2017 9:29
by BakSeeDaa
Updated the script today to version 1.0.1. It's now easier to configure.

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Saturday 30 September 2017 15:48
by DvD
I dont get it.. where does it look in the unifi controller for the hostname of the phone ?
So where do i set the hostname in this script ?

Daniel

EDIT:

I think I got it :
cellPhones["xxxxxxx"]=123
the xxxxx part is the name of the device listed in the Unifi Controller

Is there a way to speed up the process that the controller gets rit of the device when its offline ?

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Monday 09 October 2017 19:50
by Maes
This script is awesome.
I was using it until I updated to the latest beta (3.8563) today and it stopped working :(
Haven't figured out yet why

EDIT: It fixed itself :D

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Monday 09 October 2017 22:26
by sach
Works great!
Thanks for this!

Sach

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Friday 13 October 2017 0:08
by Scriptonusman
Just made an account to send my appreciation.

Thank you for making and sharing this!

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Thursday 02 November 2017 9:57
by PaulM
I was looking for a script like this, super! I did everyting as mentioned but when I run the script i got the following error:

Code: Select all

unifi-detect.sh: 7: unifi-detect.sh: Syntax error: "(" unexpected 
I really has no idea. Is the problem in line 7?

Code: Select all

numProcs=( $status )
Who can point me in the right direction?

and it works! Perfect, many thanks!

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Tuesday 07 November 2017 12:28
by PaulM
Right, I run the script now succesfully for 5 days. And I'm not quiet happy with it. Both for the android phone as for the iPhone I want to detect presence, I got a lot of false negatives.

Am I the only person with this problem? And if so , how can I solve the false negatives?

--Edit:
Problem solved. Appeared that the filename was not exactly the same as mentioned in the script for checking if the script is already running. So, a lot instances of the script were running.... I matched the names and now it's seems quiet accurate !

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Wednesday 15 November 2017 23:27
by olsonn
Nice script, works perfect. thanks!

What about this idea:
Do the same for "neighboring access points' to detect if my car with AP was seen (last detection)

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Thursday 30 November 2017 21:37
by kevster
Great script. Starting to use it now to turn on/off a virtual switch for the site/location state based on devices being 'home'

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Sunday 17 December 2017 7:23
by denver
Is it possible to install this script onto the little unifi controller.

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Sunday 17 December 2017 11:15
by denver
I meant the Ubiquiti Unifi Cloud Key unit as it can be SH'd into using terminal on the Mac

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Monday 18 December 2017 8:04
by BakSeeDaa
denver wrote: Sunday 17 December 2017 7:23 Is it possible to install this script onto the little unifi controller.
It can be installed on any linux server that has access to your LAN and your Domoticz server. You need to have enough privileges on the linux server to run the commands in the installation instruction.

Re: Presence detection using UniFi Controller (Ubiquiti Networks)

Posted: Monday 08 January 2018 21:43
by pro2call
Hello BakSeeDaa,

I'm using an $ sign in my unifi password and i'm getting the error below:

Code: Select all

Running unifi_detect.sh 1.0.1
{ "data" : [ ] , "meta" : { "msg" : "api.err.LoginRequired" , "rc" : "error"}}
401
Exiting with a result code of : 401
Im using unifi version 5.6.29

Please advice