Introduction
In this tutorial, I am gonna show you how to build a simple application that detects motion and sends notification to the your smart phone using raspberry pi and camera module. If there are something or someone moving in the camera setup field, you will get notified to your phone or web browsers.
The notification comes with text, still image, and video. that you can view it right on iOS or android.
The application is pretty simple. It utilises the free software and services such as picamera, ffmpeg, and pushbullet.
I will walk you through the architect, flow chart, and explain the main python functions. At the end of this video, you can build your own application or customize the already built one as you wish.
Let start!
Hardware
- Raspberry Pi 3
- Camera Module V2
- Sandisk Micro SD card 8GB
- Power Supply 5V, 2.5A
- Optional: Heat sinks
- Optional: Simple case or Fancy Case
Or you can buy all-in-one set here.

Specification
This section explains the specification of application including app structure, and general flow chart. You will have a clear vision about what application does.
Application Structure
There are 3 actors play together to build up the application. (1) RaspberryPi&Camera module as the data source that continuously scan for motion and recording video at the same time, (2) PushBullet as the message-broker to send messages(text, still image, and videos) back and forth between RaspberryPi and Mobile/Web, and (3) mobile/web acts as “notifyee” who receives the still image and video of motion. The communication is two ways though. It means you can send a command from mobile or web to Raspberry Pi for particular action such as “@snap” (for instantly take a photo) or “@check” (to get current system information of Pi).

General Flow Chart
When the script launch, it takes 2 seconds to warm up the camera to make sure everything works properly. Then jump right into motion scanning. If moving happens, The Pi will capture a still image and send notification to phone immediately. At the same time, Pi keeps recording the moment for a few more seconds. After that a mount of time, if moving is still there, Pi re-capture a new image and send a new notification. Until no motion anymore, the recorded videos will be pushed to mobile to confirm the motion end. The system goes into motion scanning state. The programe loops again and again as this flow.

Just Work
If you can’t wait to see it works for you, this section is for you. You will understand the source code later. For now, everything you need is to make the application up running.
Step1: Setup Pushbullet
First, you need to register a pushbullet account get the key for notification. Goto https://www.pushbullet.com, you can either register with google email or facebook. In my case, I use gmail. After successful signup, Let login and goto Settings–> Account to create a API access token. We need this token for Raspberry Pi to push notification. Just note them down some where.

Second, on mobile, the bushbullet application is ready for both iOS and Android. So, install it. Make sure you login with the pushbullet account that you just registered.


Step2: Download software
I recommend you download and install the ready-to-work image in Resources section to save your ton of time for setup necessary software and libraries. Otherwise, you can setup from the brand-new Jessie. That’s fine.
This application builds on top of standard Raspbian Jessie released on 2017-04-10 that downloads from official website of raspberry pi. You also need ffmpeg for video convert from h264 to mp4 to view directly on your phone or web browser, and pushbullet python library for notification. One note for ffmpeg that it is not ready for install via “apt-get” command on Jessie, you have to compile it from source code. The compilation time takes about 3 hours. The source code of application is mostly written in Python.
Now let download the ready-to-work image, this file size is huge, it’s about 2.7GB. So now should be the coffee time.
Step3: Flash Image to Pi
Oh right, you have downloaded the image successfully, now let unzip and flash it to your SD card. I used the sandisk micro sd card 8GB. I’m using MAC. In case you don’t know how to flash image to SD card, check this tip. If you’re on windows, you can flash with WIN32DISKIMAGER. The flash takes about 20 minutes, coffee again. (make sure you don’t drink too much)
1 2 3 |
$> sudo dd bs=1m if=/[your_dowload_path]/iotbreaks_PiCameraNotifier_V1.0.img of=[The SD Card] |
Step4: Enter the pushbullet access token
Now is show time, let take a look how it works. Insert the SD card, power Pi up. The application source code is placed right on the Desktop. You only job now is enter the pushbullet key as following:
1 2 3 4 |
$> cd ~/Desktop/PiCameraNotifier/ $> vi main.py |

Save the main.py and reboot the pi. Enjoy the result!

Step5: Play around
Take a look at pushBullet application on your phone, you should see a message that tells The application is up running. The first message should be “PiCameraNotifier app starts!”. Right swipe that message to bring you to chat screen of PushBullet. Later on, all images, videos, and texts from RaspberryPi will be sent to this chat screen. Now let try moving something in front of camera to see the magic happens. Use QuickView on iOS to view motion video. Here is my example.
Under The Hood
You want to learn deeply how source code works, this section is for you. In this section, I will explain very detail about how the code works along with its flowchart. You will be able to customize the code to add new commands, change the video or image size, store files, or what ever you need.
There are 2 python files you need to care of, they are main.py and push.py. You may guest the function of each file by its name, right? main.py is all about logic of application and push.py takes care sending notification and receive the command.
main.py
At app launch, I create two important objects – camera and notificationHandler. Those objects are used in all functions below.
1 2 3 4 5 6 7 8 9 10 11 12 |
camera = picamera.PiCamera() notificationHandler = NotificationHandler(PUSHBULLET_KEY,didReceiveCommand) def main(): global isMotionDetected global notificationHandler logging.info("### Initialize Camera") cameraInitialize() pushData = {'type': 'TEXT_MESSAGE', 'text': 'PiCameraNotifier app starts !'} notificationHandler.pushToMobile(pushData) |
We initialise camera for motion detection and recoring ahead into circularIO. The reason we need to record ahead is because we want to have a video about the moment before motion detected. We have no way to predict when something will happen, so we have to record in advance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
def cameraInitialize(): logging.info("cameraInitialize: for (1) motion detection, and (2) circularIO recording") global camera # for motion detection motionAnalysisPort=2 camera.start_recording( '/dev/null', splitter_port=motionAnalysisPort, resize=(640,480), format='h264', motion_output=DetectMotion(camera, size=(640,480)) ) # for circularIO recording HDVideoRecordPort=1 global stream camera.start_recording( stream, format="h264", resize=(640,480), splitter_port=HDVideoRecordPort) |
When motion detected, the function didDetectMotion() will be called. Pi will capture a still image and send notification to mobile via captureImage() function. Then It keep recording 2 more seconds to complete a video. That video will be pushed when the scheduled timer expired. Take a look at writeVideo() function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
class DetectMotion(picamera.array.PiMotionAnalysis): def analyse(self,a): global isMotionDetected a = np.sqrt(np.square(a['x'].astype(np.float)) + np.square(a['y'].astype(np.float))).clip(0, 255).astype(np.uint8) if(a > 60).sum() > 10: logging.info("motion just detected") isMotionDetected = True didDetectMotion() else: isMotionDetected = False def didDetectMotion(): global isRecordingMotion if isRecordingMotion: print("is Recording Motion ...") else: isRecordingMotion = True print("start Recording Motion ...") global notificationHandler global camera pushData = {'type': 'TEXT_MESSAGE', 'text': 'Hey! someone sneak into your room. Check it out!'} notificationHandler.pushToMobile(pushData) fileName=time.strftime("%Y%m%d_%I:%M:%S%p") # '20170424_12:53:15AM' logging.info("push image...") captureImage(fileName) camera.wait_recording(7) writeVideo(fileName) isRecordingMotion = False |
In case you send a command to Pi, “@snap” for example, the function didReceiveCommand will be called and proccess accordingly. The same operation goes for “@check” command.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def didReceiveCommand(command): global notificationHandler if command == "@check": logging.info("get system info") process = subprocess.Popen([ WORKING_DIR + 'systemInfo.sh'], stdout=subprocess.PIPE) out, err = process.communicate() pushData = {'type': 'TEXT_MESSAGE', 'text': out} notificationHandler.pushToMobile(pushData) if command == "@snap" : fileName=time.strftime("%Y%m%d_%I:%M:%S%p") # '20170424_12:53:15AM' captureImage(fileName) else: logging.info("Command not supported: " + command) logging.info("send notification to response") |
push.py
Now let take a look on push.py that functions transmit and receive the notification.
For Transmition, The sending out messages are text, image, and videos. To minimize the crazy things happen on sending, I use serial queue to sending one after one. You can leverage the CPU by changing the maximum thread number to 2 or more
1 2 3 4 5 6 7 8 9 10 11 |
def __init__(self, pushBulletAPIKey,didReceiveCommand): # Setup pushBullet manager self.pushBulletAPIKey = pushBulletAPIKey self.didReceiveCommand = didReceiveCommand self.pushBulletManager = Pushbullet(self.pushBulletAPIKey) thread = Thread(target = self.__createListener) thread.start() # Setup Notification Queue self.__setupNotificationQueue() |
For Receiving, I use the “@” character to mark it as a command. Here I have defined two commands “snap” and “check” as you seen. You can define your own commands by copy those lines of code.
To feel the code better, you should checkout the repository and play arround with it. Try customize the things like camera resolution, video duration, text messages, or add new command.
Log
I write log to file /home/pi/Desktop/PiCameraNotifier/run.log just in case if error happens, or you want to check the status of running. You can change the file path by modifying the variable LOG_FILE_PATH in main.py. Here is an example of log info.
05/24/2017 02:37:06 PM =========== app launched ========
05/24/2017 02:37:07 PM ### Setup Notification Listener
05/24/2017 02:37:07 PM Starting new HTTPS connection (1): api.pushbullet.com
05/24/2017 02:37:11 PM Start main
05/24/2017 02:37:13 PM ### Initialize Camera
05/24/2017 02:37:13 PM cameraInitialize: for (1) motion detection, and (2) circularIO recording
05/24/2017 03:21:27 PM motion just detected
05/24/2017 03:21:27 PM push image…
Auto launch the app at Pi boot/reboot
I think you wonder why the application is up running automatically after reboot the Pi as we do in above step, don’t you? I use the systemctl to config the PiCameraNotifier as a service that runs in background. Here is the configuration file /lib/systemd/system/PiCameraNotifier.service
1 2 3 4 5 6 7 8 9 10 11 12 |
[Unit] Description=My Sample Service After=multi-user.target [Service] Type=simple ExecStart=/home/pi/Desktop/PiCameraNotifier/main.py [Install] WantedBy=multi-user.target |
Resources
Summary
We have a real application that detects motion detection and notify to smart phone, run on Raspberry Pi 3. This application should work normally with raspberry pi zero or Pi 2.
You may wonder if is it realtime. Nah It’s not realtime, but fast enough to be aware what happen in the camera setup place.
This application does not require coding skill, but You can modify the source code as your need to add more features or customise the function.
We have very clear process for real product development. We know architect, flowchart, source code. and How those things dance together.
In case you get stuck somewhere, write your question. I will read and answer.
If you like the video, please subscribe the channel, share, and thumps up. That will inspire me to produce more helpful videos. Have a good time!
Update 1 : (01 June 2017)
+ While you testing the app, it may run out of Pushbullet quota – 500 message per month for a free account and you can’t receive notification anymore. To overcome this issue, I think you can do two things: (1) register multiple accounts and switch between them, or/and (2) customize the source code to not push text anymore, only push images and videos.
+ One more think I experienced when making the tutorial that If we push too many messages in a short period, the Pushbullet server will return that it temporarily holds the notification. Again, to overcome this issue, you can do the 2 things I mentioned above.