How I have my camera equipped PiZeros alerting me, when they detect motion

So I’ve got the Raspberry Pi’ all set up, the Diskstation streaming from them. Now I needed alerting. There are two options. via Synology’s Surveillance Station or directly from the Pi’. I chose the latter (and explain why), but we’ll go through both of them.

1. Alert notifications from the Diskstation.

This will actually give you notifications within a few minutes. You can have email, sms and push alerts here. All is done via Notification-App in the Surveillance Station:

  1. Select the Notification App and in it configure emails. I was using gmail to send them, and Synology added a nice oauth-Option here to get this enabled in seconds (in the screenshot it is already enabled). You’ll just need to authenticate with gmail from there and allow the Diskstation to use the account to send mail I highly recommend to set the interval limit here, so that the station waits at least x minutes before sending another email.
  2. I didn’t use SMS notifications, but had a try with push notifications. This works with the **DS Cam** app from Synology. You have to have it one the phone, and once its paired with your Diskstation, you can receive notifications via push.
  3. Under Settings you’ll find all the possible events you can be notified on. De-Select those you don’t need (or leave them on, if they cannot happen, you won’t be notified anyway). And you can set a schedule, which is the 2nd limiting factor to make sure you’re not getting too many false positives (next to the interval limit from #2 above).

That’s it. Shouldn’t take much more than a few minutes. Intuitive and user-friendly setup. While this probably works really well in places where people leave and come at fixed times (I can see this working really well at working places or an office, etc.), it doesn’t work for me. We do not always leave at the same time for work, nor do we come back at the same time. The schedule just isn’t flexible enough here, and I would definitely forget to adjust it, once we go on vacation. And it got me a ton of false positive alerts because of that:

So what’s the alternative? Let the Pi’ do the alerting, because we can do scripting there! Let’s take a look at the hard way then!

2. Alert notifications directly from the SurveillancePi (RaspberryPi with camera)

More steps and more time needed on this approach. That’s what the 2nd option is going to be about. Okay details, I liked Marks approach with sending emails from motion, when the Pi detects motion. However, that’s not different from using the comfortable UI-configurable options Synology is offering. I had an idea to combine it with the principles from initalstates sensor-free presence detector.

The basically have a python script running on a loop every 5 minutes, checking if certain occupants (of a building) are in that building or not, and then visualising this on a dashboard. And they cleverly use a simple arp-scan to see if the phones of the occupants are registered in the WLAN.

I like that idea, because either myself or the wife, either one of us is on the smartsphone every few minutes, just being important. Such business and stuff. I needed to combine the two approaches, because just motion calling the arp-scan seemed to arbitrary, if in that second none of our phones were wifi-active (but maybe just a minute ago, mine was) I’d be back at square one.

Splitting up this into two parts seemed like a good idea:

  1. One script running on a loop every 5 minutes, or called via cron every 5 minutes, to detect our [phones] presence, and storing this in a file as a timestamp.
  2. The script called by motion in the event of motion being detected. This will then read the timestamp from set step above, and if the difference between this timestamp and time now is greater than ‘x’ an alert will be sent.

You’ll find both parts in the according GitHub-repository as well, with appropriately selected names.

The presence detection in a loop

Because I’m lazy, I actually have this called by cron every 5 minutes, instead of a proper while-looped script. Most important thing done by the script is that it writes a timestamp (in seconds since epoch) into a file:

filename_presencelog = '/home/pi/motion_conf/presencedetect.log'

I also have a lot of debug output created by the script. All of it is written into a debugpresencedetect-Log, one per day. That’s so I could find out (and now you can) if when why a mail was sent or not, and if timings needed tweaking. The debug logs are stored in the same folder as the image snapshots, and with a nice cron job, you can get rid of all files of a certain age in this folder to avoid the disk being filled to the brim:

0 * * * * find /home/pi/motion_capture/ -iname "*" -mtime +7 -delete

So with all the debug output lines explained and out of the way, let’s take a look at the important parts of the script.

# Presence check for these occupants:
occupant = ["John", "Tom", "Kate"]
# MAC addresses of the phones
address = ["XX:XX:XX:XX:XX:XX", "XX:XX:XX:XX:XX:XX", "XX:XX:XX:XX:XX:XX"]

Enter names of your occupants (if you like – I did to make the logs easier to grasp for me), and the MAC-addresses of the according phones. I did not use iPad/laptop MAC-addresses, because if intruders feel particularly snoopy, and switch on the laptop before stealing it, I may not get an alert. So only MAC-addresses of phones which should be in close proximity to the owner at all times.

output = subprocess.check_output("sudo arp-scan -l", shell=True)
time.sleep(20) # give the arp-scan enough time
...
while i < 3:
    if address[i] in output:
        try:
            fpl = open(filename_presencelog, 'w')
            time_now = time.time()
            fpl.write(str(time_now) + '\n')
            fpl.close()
            ...
        except:
            ...

The output of an arp-scan within your WLAN is checked, if any of the configured MAC-Addresses are listed. If at least one is, a timestamp is saved into a presence log. This happens in a try-except block, because the other 2nd script is reading the same log, and it could be that they both try accessing the file at the exact same time. I didn’t want to risk the script crashing there then.

If no known MAC-Address is found, the script writes an according entry into the debug log, for you know… debugging.

Sending a “Motion detected” email via a Python script

This is the 2nd half of the deal. This script is called by motion in the event of detected motion. More specifically, we configure motion to call the script when it saves a picture (of the motion event), because only then it makes sense to send the email (because pixx or it didn’t happen!). So we change the ; on_picture_save-line in the motion.conf to

python /home/pi/motion_conf/sendmail.py %f recipient@email.com

As you can see the sendmail.py script gets two parameters. A file (link to actually) and an email address. To be able to send mails, the following is necessary on the Pi:

$ sudo apt-get install ssmtp && apt-get install mailutils && apt-get install mpack
$ sudo nano /etc/ssmtp/ssmtp.conf

It is necessary to set the following items/lines:

mailhub=TARGET_SMTP_SERVER
hostname=SurveillancePI
AuthUser=USER
AuthPass=PASSWORD
FromLineOverride=YES
UseSTARTTLS=YES

Replace TARGET_SMTP_SERVERUSER and PASSWORD with according content for your email account. If you are using gmail, get an application password like so: Sign in using App Passwords.

With the requirements checked, let’s see the sendmail.py. It will write its own daily debug log as well, to help fine tuning the timings, to balance a reasonable amount of false positives with a not too large gap where intruders may get in without alerts (for example shorty after we left the house).

The script gets two parameters (arguments), that means it needs to import the sys module. The rest is nothing new.

import sys
...
image_to_send = sys.argv[1]
recipient = sys.argv[2]

Then it reads the last presence timestamp, also with a try-except block, in case the file is opened right now (and the other script is writing into it right now). In that case we’ll set the presence to ‘0’ and will alert definitely.

try:
    fpl = open('/home/pi/motion_conf/presencedetect.log', 'r')
    last_presence = str(fpl.readline())
    fpl.close()
except:
    fdebug.write(time.strftime("%Y-%m-%d %H:%M:%S") + ' access to /home/pi/motion_conf/presencedetect.log failed \n')
    last_presence = '0'

There is actually another try-except block here:

try:
    fsl = open('/home/pi/motion_conf/sentmail.log', 'r')
    last_sentmail = str(fsl.readline())
    fsl.close()
except:
    fdebug.write(time.strftime("%Y-%m-%d %H:%M:%S") + ' access to /home/pi/motion_conf/sentmail.log failed \n')
    last_sentmail = '0'
time_diff_sentmail = time_now - float(last_sentmail)

This will try (haha) to read a timestamp of the last sent mail into a log. Because if the script just sent an email seconds (or a few minutes ago), it’s likely that it is the same motion event, and then I figured I probably don’t need another email. If reading the file was not possible, the timestamp is set to 0 as well.
This timestamp is used a bit later to decide if sending an email is appropriate or not.

if time_diff_presence > 1800  and time_diff_sentmail > 600:
    subprocess.call(["mpack", "-s", "Your Mighty Security Camera has detected Motion!", image_to_send, recipient])
    # print ("Mail Sent")
    fdebug.write(time.strftime("%Y-%m-%d %H:%M:%S") + ' Mail sent - Time diff lastpresence: ' + str(int(time_diff_presence)) +  ' seoncds - Time diff lastsentmail: ' + str(int(time_diff_sentmail)) + ' seconds \n')
    fsl = open('/home/pi/motion_conf/sentmail.log', 'w')
    time_now = time.time()
    fsl.write(str(time_now) + '\n')
    fsl.close()
else:
    # print ("No Mail Sent")
    fdebug.write(time.strftime("%Y-%m-%d %H:%M:%S") + ' Mail not sent - Time diff lastpresence: ' + str(int(time_diff_presence)) +  ' seoncds - Time diff lastsentmail: ' + str(int(time_diff_sentmail)) + ' seconds \n')

fdebug.close()

The final code. If the last presence was at least 30 minutes ago, and the last sent email was at least 10 minutes ago, this will send us an email, when the Pi’ did detect a motion event. Otherwise it will just write a log entry, with the time differences, so that you can learn from than and adjust them if necessary.

Conclusion

Two really different ways of motion alerts, one very comfortable and user-friendly to use, which will work very well in scheduled environments. And the 2nd more, with more work to set it up with the benefit of more flexibility. Go ahead build yours!

You’ll find everything script-wise from this guide at GitHub as well.

Please follow and like us:
 

herrschroedinger

 

Leave a Reply

Your email address will not be published. Required fields are marked *