This article will annotate the creation of a smart doorbell, using a Raspberry Pi. Enlightened by the internet of things (IoT) technology sprouting in our neighborhoods lets take this opportunity to develop our own IOT device given all the hype. Hopping on the wagon lets begin with an intuitive prototype of a smart doorbell. The concept design should utilize a push button to text my cell phone a web address to view a video stream channeled by the Raspberry Pi.
- Downloading Rasbian
- Configure Internet Connection
- Twilio Account with project SID, the authorization token, and a Twilio phone number
Before we get started it is important to update your Linux distribution before installing any other packages. For simplicity, the following examples use nano for the creation and editing of the python scripts. There are several methods for simpler ways to edit code on a remote machine, the guide won’t affect those who deviate from nano.
sudo apt-get update #Make sure that the device is up to date
sudo apt-get upgrade
sudo apt-get install nano #Install text editor
Devices used in this project
- Raspberry Pi Model 3 B+
- Raspberry Pi Camera Board v2–8 Megapixels
- Tactile Button Switch
sudo shutdown -h now # Safely powers off the Raspberry Pi
sudo shutdown -r now # Safely restarts the Raspberry Pi
ifconfig # Find your IP address
nano <FILE_NAME> #Creates file in current directory
Creating a Web Server
Let us begin by installing dependencies from the Linux package manager by running the following command. To make sure that we do not corrupt our OS distribution update and upgrade your Raspbian before any installation.
sudo apt-get install apache2 -y
Let’s test the web server, Apache already creates an HTML file in the web folder. The default page is hosted on http://localhost/ or http://<IP_ADDRESS>/. This web server will later host the live video stream feed through a Python script. You can find your IP address by taking a look at the helpful commands posted earlier.
Connecting the Pi Camera
Refer to the Raspberry Pi board schematic throughout the guide.
Connect the 8-megapixel camera into the I/O port. In order for the Raspberry Pi to register the device, restart the system using the restart command from the helpful command list above. Once we have established an SSH connection with the Pi, camera software must be enabled. Enter the Raspberry Pi configuration menu to toggle the authorization. In the terminal type the following to enter the Raspberry Pi configuration menu and follow the subsequent images.
Once the camera module has been enabled, create a file that will leverage the camera to stream to a web server. The code below exports a function that starts a video stream to port 8000. The reason for exporting it as a function is to embed the stream into its own thread in the main executable. To save the file press Ctrl+X and type Y and then Enter.
#create file by typing into console=> nano rpi_camera_live_stream.py
from threading import Condition
from http import server
# Web streaming example
# Source code from the official PiCamera package
<title>Raspberry Pi - Surveillance Camera</title>
<center><h1>Raspberry Pi - Surveillance Camera</h1></center>
<center><img src="stream.mjpg" width="640" height="480"></center>
""" class StreamingOutput(object):
self.frame = None
self.buffer = io.BytesIO()
self.condition = Condition() def write(self, buf):
# New frame, copy the existing buffer's content and notify all
# clients it's available
self.frame = self.buffer.getvalue()
return self.buffer.write(buf) class StreamingHandler(server.BaseHTTPRequestHandler):
if self.path == '/':
elif self.path == '/index.html':
content = PAGE.encode('utf-8')
elif self.path == '/stream.mjpg':
self.send_header('Cache-Control', 'no-cache, private')
self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
frame = output.frame
except Exception as e:
'Removed streaming client %s: %s',
self.end_headers() class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
allow_reuse_address = True
daemon_threads = True with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
output = StreamingOutput()
#Uncomment the next line to change your Pi's Camera rotation (in degrees)
#camera.rotation = 90
address = ('', 8000)
server = StreamingServer(address, StreamingHandler)
#Uncomment the next line if you want to demo the stream
Demoing the Video Stream
It is helpful to test each segment individually before layering the final product. This will help debug errors more effectively, by reducing the number of dependencies. To run the video stream, un-comment the last line of the rpi_camera_live_stream.py, this will invoke the deployment function. To run the python script run the following command.
Once the Python script has successfully run, you will have access to the web server that is hosting the camera stream. Open any browser (Chrome and Firefox were tested successfully) and go to http://localhost:8000.
For this segment, we will incorporate the communication between the device and the “homeowners” cell phone. Leveraging Twilio for their Python SMS service. Install the package by entering the following line into the console.
pip3 install twilio
Once that is installed let us check that everything was installed correctly by checking the version. Run the next command, and expect a positive response with a version number over 9.0.0 unless your installation specified otherwise.
# For more information on Twilio https://www.twilio.com/docs/python/install# Import Twilio
from twilio.rest import Client# Your Account Sid and Auth Token from twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)# This function will be invoked from our button event
message = client.messages.create(# Message sent to user
)# If a GUID is logged then the message was sent successfully sent#Message id for debugging on the Twilio event logs
#Uncomment the line above to demo
Tactile Buttons Are Ringing!
The finale joins all the other files into separate threads to avoid interrupts and blocks. Python supports simultaneous run executions with their multiprocessing library. In order to host the web server and listen to button events, this library will be crucial to support the prototype architectures integrity. Without separating the python modules into their own threads the program will interrupt older processes at run time.
Let’s begin by configuring the circuit board to the schematic below. On one side of the switch, we connect to GPIO pin 10. The other side of the switch needs to connect to the 5V pin (Refer to your Raspberry Pi GPIO layout) interrupted by a 10k ohm current limiting resistor to protect the input pin. In production pin 10 will be at 0V until the button is pressed closing the circuit sending 5V. GPIO pin 10 is constantly listening for input voltages, once the event fires the button_callback function is invoked. Using the send_SMS module written earlier to send a text message to the phone number specified.
# Import startCamera function from the video stream file
from rpi_camera_demo import startCamera# Import function to send SMS from the send_SMS.py file we created earlier
from send_SMS import text_user# Import Process from the multiprocessing module in Python standard library
from multiprocessing import Process# Import Raspberry Pi's GPIO library
import RPi.GPIO as GPIOdef button_callback(channel):
print("Button was pushed!")
GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BOARD) # Use physical pin numbering
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Set pin 10 to be an input pin and set initial value to be pulled low (off)GPIO.add_event_detect(10,GPIO.RISING,callback=button_callback) # Setup event on pin 10 rising edge# Define function to start the video stream
# This is necessary to initialize multi processing
print('Starting thread for video stream')
startCamera()# Assures that the entry point of the program begins here
if __name__ == '__main__':
Thread_Target.start()#Block the calling thread until the Thread_Target process terminates
message = input("Press enter to quit\n\n") # Run until someone presses enter
GPIO.cleanup() # Clean up
To finally demonstrate the final product make sure that all the independent modules are not invoking themselves. Then use python3 to invoke the button module.