How to run webcam software only when I am not home (phone is not on the LAN)?

6

7

Currently I've got my user cron starting Motion on a timer when I typically leave for work, and then killing it when I typically get home, so I can watch my cat/burglars/etc:

0 9 * * * killall motion ; motion
30 18 * * * killall motion

The config file used is ~/.motion/motion.conf and has daemon on.

But it would be better if it could detect when I'm actually home and disable the webcam during those times, and enable it at other times. I was thinking my presence could be detected by my Android phone joining the LAN. So something like

  1. A script that checks every few minutes whether my phone's hostname or MAC address is currently on the LAN
  2. A Tasker script on my phone that contacts the home computer in some way (simple web server?) when it joins a certain SSID
  3. A combination of the above
  4. ...

Any better ideas or advice about how to implement one of these? Tasker is easy to use, but costs $6, so a solution that doesn't depend on it would be useful by a wider audience.

My first attempt at the arp-scan solution doesn't work very well. It creates multiple instances of motion and doesn't detect the phone reliably, causing the camera to turn on and off sporadically. So maybe it should be more like "check every minute if the phone is present. only turn the camera on if the phone has not been seen for 15 minutes".

Ok, I wrote a python script to do an arp-scan once per minute, and it detects the phone perfectly:

2012-11-27 18:29:10.551552 No
2012-11-27 18:30:22.295997 No
2012-11-27 18:31:34.077431 No
2012-11-27 18:32:45.804675 No
2012-11-27 18:33:57.545211 No
2012-11-27 18:35:09.261680 No
2012-11-27 18:36:20.974378 Yes
2012-11-27 18:37:21.901076 Yes
2012-11-27 18:38:22.417423 Yes
2012-11-27 18:39:22.836101 Yes
2012-11-27 18:40:23.463507 Yes
2012-11-27 18:41:23.876693 Yes

So there's something wrong with cron or the way I'm starting motion or something.

I tried to run /etc/init.d/motion start instead of running it and killing it as a user, but that method doesn't work:

 * Not starting motion daemon, disabled via /etc/default/motion

So I edited /etc/default/motion to say start_motion_daemon=yes and tried again:

 ~> /etc/init.d/motion start
mkdir: cannot create directory `/var/run/motion': Permission denied

I don't even know what that means.

endolith

Posted 2012-10-25T21:43:36.220

Reputation: 6 626

Answers

5

zmode's answer is helpful, but didn't work for me. After a lot of reading, I came up with this solution:

#!/bin/sh
if arp-scan -I eth0 -r 10 android | grep -q '12:34:56:78:90:ab'
then
    echo "Phone present, killing motion"
    killall motion
    echo "Done killing motion"
else
    echo "Phone absent, starting motion"
    if ! ps -A | grep -q motion
        then
            echo "Motion is not running - starting it"
            su -c 'motion' - username
            echo "Motion started"
        else
            echo "Motion already running"
    fi
    echo "Done starting motion"
fi
exit

(The MAC address, hostname, and username need to be replaced.) It checks if the phone is on the network, using the phone's hostname android to avoid scanning unrelated addresses. It checks if motion is already running, so it doesn't start multiple instances or kill it repeatedly while it's working.

Then run sudo crontab -e to edit the root user's cron, and add a line like this:

*/5 * * * * /home/username/phone_webcam/phone_webcam.sh >> /var/log/cron.log 2>&1

This will run the script every 5 minutes, logging the output so you can debug it. Run the command tail -f /var/log/cron.log to make sure it's working. After confirming that it works, remove the logging line from crontab:

*/5 * * * * /home/username/phone_webcam/phone_webcam.sh

endolith

Posted 2012-10-25T21:43:36.220

Reputation: 6 626

5

Running a script on your computer is much easier and definitely more clean than setting up a webserver that will wait for a phone to talk to it. Therefore I'm going to go with your first idea.

Assumptions:

  • You have root access.
  • /etc/init.d/motion is used to start and stop motion.
    • systemctl start|stop motion.service for systemd
  • You connect to the same network as your phone using eth0.
  • Your cron implementation uses the crontab command.

Getting the MAC address:

Get arp-scan and run arp-scan -I eth0 -l -r 10 as root. (I found -r 10 to be important for always detecting my Android phone)

This will return a list of devices in your network. The third column should make it easy to identify your phone. Let's say we get 01:01:01:01:01:01.

Script it:

Run arp-scan -I eth0 -l -r 10 | grep -q '01:01:01:01:01:01' as root. This will return 0 only if the phone is connected.

Run crontab -e as root and append this line to check if your phone is connected to the network every minute:

* * * * * arp-scan -I eth0 -l -r 10 | grep -q '01:01:01:01:01:01' && /etc/init.d/motion stop || /etc/init.d/motion start

Save the file and quit the editor.

Keep in mind that we do not need to check if motion is running ourselves. The service script does this internally.

dset0x

Posted 2012-10-25T21:43:36.220

Reputation: 1 897

seems like sudo arp-scan -I eth0 -r 10 android is faster. when I try to run /etc/init.d/motion start as root, though, I get * Not starting motion daemon, disabled via /etc/default/motion. Normally I just run it as motion by my non-root user, which uses my settings in ~/.motion/motion.conf – endolith – 2012-10-29T19:18:48.147

1I strongly recommend using the daemon. If you still want to run as a user though; you have two options: (a) Replace /etc/init.d/motion start with su -c 'motion' username'. (b) Allow your user to runmotion` with no password in /etc/sudoers (if you use that) and add the entry to the user's crontab with the init.d file's PID checks (best to make a small script that will have the same functionality as the init.d file and call that script from your crontab instead). – dset0x – 2012-10-29T21:13:24.007

That seems to create multiple instances of motion every minute. I had been starting the daemon by running motion as the user. Is there a way to use the init.d start method, but still have it use the config file in my user home directory and still write the files to my user home directory with the user's permissions? – endolith – 2012-11-21T04:38:08.273

/etc/init.d/motion stop kills all the instances if I run it on the command line, but it doesn't do anything inside crontab – endolith – 2012-11-21T05:36:48.183

You can open the /etc/init.d/motion script and copy the process checking/killing functionality from there into a script of yours. It should work inside crontab by the way (must be in root's crontab if running as root); check your cron logs. – dset0x – 2012-11-21T13:51:56.137

3

Taking the above response as a base you can tweak it to make it work slightly better.

#!/bin/sh
if arp-scan -I wlan0 -r 10 android-11111111111111111111 | grep -qi '11:11:11:11:11:11'
then
    echo "Phone present, killing motion"
    killall motion
    echo "Done killing motion"
else
    echo "Phone absent, starting motion"
    if ! ps -A | grep -q motion
        then
            echo "Motion is not running - starting it"
            su -c 'motion'
            echo "Motion started"
        else
            echo "Motion already running"
    fi
    echo "Done starting motion"
fi
exit

Typically, for wifi the interface is known as wlan0. The name of the android device is typically android- followed by a serial number. By adding -i to the grep command you can run the search with case insensitivity (took a while to figure this one out). On my machine starting motion properly requires root access. This can be accomplished by removing the username from the su command.

With those modifications and following everything in the above answer you can get Motion to start up no problem as soon as you leave (with your phone) your house. Flawless!

astryk

Posted 2012-10-25T21:43:36.220

Reputation: 131

0

I have a bash script running every 4 minutes to do that. It works quite well. Here is the code with some explanations.

#!/bin/bash
############################################################################
## looking for iPhone, 1 if iPhone logged in, else 0
## IPhoneIP.txt contains local IP-adress (also bash-based)
IPhoneIP=$(cat /home/pi/motion/IPhoneIP.txt)
NMAP=$(nmap -sn -oG - ${IPhoneIP})
iPhoneActive=$(echo $NMAP | grep -c "Status: Up")
############################################################################
## alternatively finding iPhone with Bluetooth
if [ "$iPhoneActive" -eq 0 ]; then
    #save former value ofiPhoneActive if zero
    iPhoneActive=$(cat /home/pi/motion/IPhoneBluetoothCheck.txt)
fi
############################################################################
##if network down do nothing
NetworkDown=$(echo $NMAP | grep -c "Unable to determine any DNS servers")
############################################################################
##now checking whether motion is activ
MotionDetectionActive=$(wget -O - -o /dev/null  http://localhost:8086/0/detection/status | grep -c "ACTIVE")
############################################################################
##if iPhone in Wifi and Motion active activate
if [ "$iPhoneActive" -eq 1 ] && [ "$MotionDetectionActive" -eq 1 ]
then
    wget -O - http://localhost:8086/0/detection/pause > /dev/null 2>&1
    echo "Deactivating motion detection, iPhone entered WLAN" ##logging
fi 

if [ "$iPhoneActive" -eq 0 ] && [ "$MotionDetectionActive" -eq 0 ] && [ "$NetworkDown" -eq 0 ]
then
    wget -O - http://localhost:8086/0/detection/start > /dev/null 2>&1
    echo "Activating motion detection, iPhone left WLAN or other error" ## logging
fi

The iPhoneIP is detected on a weekly bases using

#!/bin/bash
########################################################
#writes iPhoneIP into /home/pi/motion/IPhoneIP.txt / IP-range might be different!!
########################################################
#
IP=$(nmap -sP 192.168.2.100-199 >/dev/null 2>&1 && /usr/sbin/arp -an | grep "01:01:01:01:01:01" | awk '{print $2}' | sed 's/[()]//g')
if [[ "${IP}" != "" ]]; then
    echo "${IP}" >/home/pi/motion/IPhoneIP.txt
fi

The bluetooth-detection is also bash-based using the following script (also running every 3 minutes):

#!/bin/bash
############################################################################
## bash checks whether iPhone is detected via bluetooth
############################################################################
##
############################################################################
BLUET=$(sudo l2ping -c 1 01:01:01:01:01:01 2>/dev/null | grep -c "44 bytes")
echo "${BLUET}" > /home/pi/motion/IPhoneBluetoothCheck.txt

user2165245

Posted 2012-10-25T21:43:36.220

Reputation: 1