Site icon Intermittent Technology

Domoticz: Bash script for presence detection using NMAP

Today I programmed another part of the system I envision for my new house. It’s a bash shell script which checks if either my phone or that of my girlfriend is in range and depending on if it is or not it changes a switch in Domoticz. That way I can automate all the lights turning off when we are not home, and coming back on when we are!

Detecting the presence of the phones

I looked at several ways of doing this, from a simple ping script to a arp-scan, etc. 

 
Ping is not reliable enough because smartphones use aggressive sleep modes to try and conserve power when they can. Arp-scan was not usable for me since I use a routed wireless network and it can’t travel past my gateway.


NMAP

I searched a bit online and found that nmap has a “no port scan” presence detection ability and tried it out. With all of my Android devices and in my routed setup it has worked great. Even when a device does not respond to ping anymore it does still respond to this request and for the last few hours I have been testing with it, it has worked flawlessly.

Ping example:

root@domoticz:/home/quindor# ping -w 10s 10.24.1.10
PING 10.24.1.10 (10.24.1.10) 56(84) bytes of data.

--- 10.24.1.10 ping statistics ---
10 packets transmitted, 0 received, 100% packet loss, time 9072ms

root@domoticz:/home/quindor#

Nmap example:

root@domoticz:/home/quindor# nmap -sn 10.24.1.10

Starting Nmap 6.40 ( http://nmap.org ) at 2015-02-01 01:50 CET
Nmap scan report for 10.24.1.10
Host is up (0.43s latency).
Nmap done: 1 IP address (1 host up) scanned in 1.46 seconds
root@domoticz:/home/quindor#


As you can see, the ping response hangs (set maximum wait time to ~10s) but the nmap responds that same host is up. If I try to namp the same address but turn WiFi off on my phone it correctly mentions that the host is not up. There is no delay in this such as decaying arp records, etc.


So this seems to work for all my Android devices, I can’t say if Apple or anything else will work, but it’s worth a shot I would say!


The need for static IP addresses

Using any kind of presence detection (except ARP) will require your devices having static IP addresses. 
 
In my setup I have static reservations in my DHCP server (Running on a Mikrotik Routerboard) so that the phones always get the same IP address. This way we can always verify if the device is in the house and connected to the WiFi network, or not.


Script for using with Domoticz

In Domoticz you need to create a Dummy switch which we are going to switch using a script. The device will turn on when someone is at home and turn off when everyone leaves home. This way we can verify if someone is present at home, or not.
 
A quick description of how to do that is by going to Setup –> Hardware and use or add a “Dummy” device. Once you have created that, click “Create Virtual Sensors” and create a switch.
 
Virtual Sensor
This switch will be controlled using a script. At first I looked at using a LUA script, as I do with my LED dimmer but I had trouble getting this working correctly. So instead I created a bash script which runs in the OS which in my case is an Ubuntu VM running on VMware ESXi 5.5. It controls the switch using HTTP JSON commands.
 

Bash Script

To use this script you will need nmap, curl and grep. You can easily install those on a Linux based system. For Windows you will probably need cygwin or the separate tools and put them in your system path.

–update 2015-02-03

I’ve made the whole script run from variable which can be stated in the beginning of the script. Only the URL is not a variable because 90% of the people will be running the script from the same machine as where Domoticz is running.

I have also implemented a check to see if the switch is already ON or OFF so that it doesn’t keep switching the Domoticz switch causing all kinds of weird things to happen. 😉 That also means that if you change something, those changes will not get overwritten except by the OFF or ON command when it occurs.


I also did a little bit of cleanup work and re-wrote some stuff.


The script I’m currently using is the following:

 

loop=1
sleep=10
switch=40

while [ "$loop" -eq "1" ]
do

echo ""
echo ""
echo ""
echo ""
echo Phone on = 0, Phone off = 1
nmap -sn 10.24.1.10 | grep -q latency
phone1=$?
echo Phone Name1 = $phone1
nmap -sn 10.24.1.11 | grep -q latency
phone2=$?
echo Phone Name2 = $phone2
total=$(($phone1 + $phone2))
echo Phones Total command = $total

if [ "$total" -gt "1" ];
 then
  echo Detected 0 phones, Checking status switch $switch;
  curl -s "http://127.0.0.1:8080/json.htm?type=devices&rid="$switch"" | grep '"Status" : "Off",'
  switchon=$?
   if [ "$switchon" -eq "0" ];
    then
     echo Switch $switch is already OFF, skipping sending command to Domoticz;
    else
     echo Switch $switch was ON, turning switch OFF; curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx="$switch"&switchcmd=Off";
   fi
 else
  echo Detected 1 or more phones, Checking status switch $switch;
  curl -s "http://127.0.0.1:8080/json.htm?type=devices&rid="$switch"" | grep '"Status" : "On",'
  switchon=$?
   if [ "$switchon" -eq "0" ];
    then
     echo Switch $switch is already ON, skipping sending command to Domoticz;
    else
     echo Switch $switch was OFF, turning switch ON; curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx="$switch"&switchcmd=On";
   fi
fi
echo ""
echo ""
echo ""
echo ""
echo Execution done, sleeping for $sleep seconds
sleep $sleep
done


What the script does is create a loop (sleep time at the end). This loop runs the NMAP command with a grep. If it’s succesful (grep finds the word “latency”) it returns with exit code 0. I check for this exit code and copy it to an environment variable. I do this also with the second phone.


After this I have two environment variable which are either 0 or 1 (or higher). I add these up to form another variable. Then I use a statement, if this variable is higher then 1, turn off the switch (no one is home). If it is 1 or lower, the switch needs to be on.


Be sure to change the IP address to where you are hosting Domoticz (probably localhost like mine) and to lookup your switch Device Index number and change it in the code. It’s the “idx=40″ part.


This will need to be changed reflecting the amount of devices you are checking.


Currently the sleep is 10 seconds. This is quite short, but I have not yet noticed any negative effects because of it. Domoticz checks it’s blocky scripts every 30 seconds, so the maximum time it can take to have an effect is ~39 seconds!


After this you just need to use a way of running the script. For now I’m starting it using a screen session after my machine boots. But you can also start it automatically during startup, or start it periodically using a cron job (remove the sleep line).


You can use this Switch in a LUA script or in a Blocky script inside of Domoticz. This post will not go into that right now, I might do another post about how to create that another time!


And that’s it! The switch should now get automatically updated in Domoticz.


Any questions or remarks, please let me know. If you are using it, drop me a line, always nice to know!
Exit mobile version