1. Home
  2. Docs
  3. Device Kits
  4. Motion Detection and Alerting Using a Raspberry Pi and Avimesa.Live

Motion Detection and Alerting Using a Raspberry Pi and Avimesa.Live

In this Device Kit, we’ll be attaching a PIR (passive infrared) motion sensor to a Raspberry Pi and sending its output to Avimesa.Live in order to trigger an alert. We’ll be using an Avimesa Gadget client on the Raspberry Pi to relay our sensor’s output to Avimesa.Live.

alt text

To successfully set up this Device Kit, a rudimentary knowledge of electronics, the Linux command line interface (CLI), and the Python (3) programming language is (probably) required. Our PIR motion sensor will require nothing more than GPIO to give us the readings we require. On the Raspberry Pi, we’ll be using the Python programming language to drive (or control) Gadget as well as to read our PIR motion sensor’s output. To be more specific, we’ll make extensive use of two Python modules: the standard library subprocess module and the third party gpiozero module to, respectively, drive Gadget and deal with the Raspberry Pi’s peripherals (in our case, GPIO). The gpiozero module is the recommended Python module for controlling the Raspberry Pi’s peripherals.

Components

(1) If you need help flashing an SD card with a Raspbian image, please visit here.

(2) To install the Python module gpiozero, you’ll first want to make sure your repository list is up to date by running sudo apt update. Second, install the module for Python (3) using the following command: sudo apt install python3-gpiozero. If you run into any issues, please visit here for help troubleshooting.

Hardware Setup

Connecting the PIR motion sensor to the Pi is simple: attach the sensor’s +5V connection to a 5V pin on the Pi, attach the sensor’s GND connection to a Ground pin on the Pi, and attach the sensor’s OUT connection to one of the Pi’s GPIO (I’ll be using GPIO17). NOTE: The Pi pin connections stated here are the physical Broadcom connections. This link contains a great representation of the Raspberry Pi 40 pinout header and the associated Broadcom connections for assistance in determining what connections to make.

Avimesa.Live Setup

First, you’ll need an active Avimesa.Live account.

Second, you’ll need to obtain a valid set of Avimesa device credentials:

Software

Let’s use this script first to make sure everything is working (copy the following into something like pir_sense_test.py, insert your valid device credentials, and run using python3 pir_sense_test.py):

import subprocess

from time import sleep
from gpiozero import MotionSensor

def send_message(motion_detected):
    gdgt_args = ['/usr/local/bin/avmsagadget',
                 '-i',
                 'deadbeefdeadbeefdeadbeefdeadbeef', # DEVICE ID
                 'deadbeefdeadbeefdeadbeefdeadbeef'] # DEVICE AUTHENTICATION KEY
    gdgt_timeout = 5 

    gdgt_input = ('{{"ch_idx":0,"ch_data":[{{"data_idx":0,'
                  '"units":1,"val":{0}}}]}}\nrun\n'
                  'exit\n').format(motion_detected)
    gdgt_input = gdgt_input.encode()

    try:
        gdgt_complete = subprocess.run(args=gdgt_args,
                                       input=gdgt_input,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       timeout=gdgt_timeout)

        print("STDOUT:\n" + gdgt_complete.stdout.decode())
        print("STDERR:\n" + gdgt_complete.stderr.decode())

    except subprocess.TimeoutExpired:
        print('Gadget timed out after {0} seconds!'.format(gdgt_timeout))

    except subprocess.CalledProcessError as E:
        print('Gadget exited with non-zero return code {0}'.format(E.returncode))
        print('STDERR:\n' + E.stderr.decode())

if __name__ == '__main__':
    pir = MotionSensor(17)

    while True:
        try:
            pir.wait_for_motion()
            send_message(1.0)

            pir.wait_for_no_motion()
            send_message(0.0)

        except KeyboardInterrupt:
            break

    pir.close()

If everything is wired up correctly, you should be able to wave your hand (or dance if you’re feeling froggy…) in front of the sensor and a message should be sent off to the cloud. You’ll see Gadget>>> Message transmission successful! if everything is truly correct. If you’re interested in what’s going on in this script, you can check out the MotionSensor Python class here for more information. If you’re having trouble, check the wiring of your sensor and make sure you’ve input your device credentials into the script.

Now let’s really get this thing set up: let’s turn it into a service. First, copy the following into something like pir_sense:

#!/usr/bin/python3

import subprocess

from time import sleep
from gpiozero import MotionSensor

def send_message(motion_detected):
    gdgt_args = ['/usr/local/bin/avmsagadget',
                 '-i',
                 'deadbeefdeadbeefdeadbeefdeadbeef', # DEVICE ID
                 'deadbeefdeadbeefdeadbeefdeadbeef'] # DEVICE AUTHENTICATION KEY
    gdgt_timeout = 5 

    gdgt_input = ('{{"ch_idx":0,"ch_data":[{{"data_idx":0,'
                  '"units":1,"val":{0}}}]}}\nrun\n'
                  'exit\n').format(motion_detected)
    gdgt_input = gdgt_input.encode()

    try:
        gdgt_complete = subprocess.run(args=gdgt_args,
                                       input=gdgt_input,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       timeout=gdgt_timeout)

    except subprocess.TimeoutExpired:
        pass

    except subprocess.CalledProcessError as E:
        pass

if __name__ == '__main__':
    pir = MotionSensor(17)

    while True:
        try:
            pir.wait_for_motion()
            send_message(1.0)

            pir.wait_for_no_motion()
            send_message(0.0)

        except:
            break

    pir.close()

Move it to /usr/local/bin using mv pir_sense /usr/local/bin and change its permissions using sudo chmod 755 /usr/local/bin/pir_sense.

We’ll also need to create the following file ~/.config/systemd/user/pir_sense.service:

[Unit]
Description=PIR Sensing Service

[Service]
ExecStart=/usr/local/bin/pir_sense
Restart=on-failure

[Install]
WantedBy=default.target

This file is used by systemd to manage services (we’ll be installing our service under a non-root user). Here is a lovely little beginner’s guide on installing and managing services in Linux.

Once our service files are in place, let’s run this first to allow our service to run without our system requiring us to login:

sudo loginctl enable-linger $USER

Next, we’ll need to run the following to make systemd aware of our .service file:

systemctl --user daemon-reload

Finally, let’s enable our service to start on system start-up and also start our service:

systemctl --user enable pir_sense
systemctl --user start pir_sense

We can also check on our service with:

systemctl --user status pir_sense

Avimesa.Live Integration

First, let’s add our sensor in Avimesa.Live:

And finally, let’s add an alert to let us know whenever our sensor has detected motion:

NOTE: Make sure you have an email and / or phone number registered to your Avimesa.Live account!