Build

How to Build Your Own Smart Home in an Afternoon

7 min read Michael Carroll on Dec 13, 2022
Try PubNub Today

Free up to 1MM monthly messages. No credit card required.

Subscribe to our newsletter

By submitting this form, you are agreeing to our Terms and Conditions and Privacy Policy.

Learn how you can easily build three smart home projects on a Raspberry Pi using Python and PubNub.

As new IoT (Internet of Things) technologies emerge, smart homes and home automation have become increasingly common. Homeowners use Ring's suite of products to protect their homes. This system includes motion sensors, video doorbells, smart locks, and security cameras as their home security.

Homeowners can also implement IoT technologies to create smart homes to assist in their daily lives. Smart thermostats, such as the Nest Thermostat, manage the temperature in smart home systems. Smart displays like Lenovo's Smart Display show customized information through a screen, typically with other connected devices via Bluetooth or WiFi. Smart light bulbs, such as Philips Hue, are used to control light switches and other smart switches. Bose's suite of products allows customers to play music through their smart speakers by using their phones. Customers can even use voice control to manage other IoT devices with personal assistant devices such as Google Home, Amazon Alexa and Amazon Echo, and Siri using voice commands to control devices connected to WiFi using smart plugs. Although there are many existing smart home devices, you can learn how to build your own customized homepod using PubNub.

At PubNub we specialize in bridging the wondrous world of IoT to anyone who seeks it. With our real-time data API and Virtual Spaces Platform, you can depend on PubNub to power your smart home hub. Follow along to see how you can build your own smart home with three smart home technologies.

How to build a smart home system

What makes a home smart? The answer is automation and centrality. A household must automate all of its basic tasks and be able to transmit information to and from a central location (typically a home app). You'll implement these two foundations of IoT in building these technologies using PubNub:

  • Smart Light – automation of lights

  • Light Detector – data centralization

  • Door Detector – data centralization

Required Materials

The following materials and hardware are required to create these three IoT technologies that make up this smart home technology.

Raspberry Pi

In order to program our IoT technologies and have them communicate between you and your home, you’re going to need what’s called a microcontroller. While there are many options for microcontrollers, perhaps the easiest one to use is the latest version of a Raspberry Pi (RPi). If you’ve never set one up before, the instructions can be found on the product's website.

Relay

In order to make sure that we can plug any electronic (no matter how strong the voltage) into our RPi without frying it, we’ll need what’s called a relay. A relay is essentially a switch that will be able to handle high currents and voltages so that the RPi doesn’t have to.

image4 1024x400

A Lamp

To make a smart lamp, you’ll need a simple, cheap lamp. Pick up a used lamp from a second-hand store or find one online.

Phototransistor

In order to build a smart light sensor, you’ll need a phototransistor. Like the relay, the phototransistor acts as a switch. The phototransistor will only allow current to flow through in the presence of light, so this will be a perfect sensor to see if your house lights are on.

image1 1024x768

Tin Foil and Wire

In order to create a door sensor, you will need to use tin foil contact pads that allow electricity to pass if the pads come into contact. This way, you can attach a pad to a door and its frame so that every time the door is closed, the pads make contact, and let the Raspberry Pi know that our door is closed. You'll need to create two tin foil pads, with wires connected to each of the pads. Attach one pad to a door, and the other to the frame using painter's tape.

IoT Tin Foil

Hardware Setup

Smart Lamp

In order to make a smart lamp out of any ordinary lamp, you need to splice the power cable into two parts (when unplugged of course) and strip some of the casing to expose the wires. Every lamp has a power cable (typically red) and a ground cable (typically black).

IoT Splice Power Cable

Now grab your relay and connect the ground wires back together, connect one end of the power wire into the NO (Normally Open) port of the relay, and the other end into the NC (Normally Closed) port of the relay.

IoT Relay Connections

Now in order to connect the lamp-relay module to the RPi, connect them to the GPIO pins of the RPi.

image8 1024x601

Light Sensors

The light sensor circuit is much more simple to implement. Wire your phototransistor to one of the RPI’s GPIO pins.

image10 1024x904

Door Sensor

For the door sensor, wire one pad up to a GPIO pin on the RPi and the other pad to ground (for diagram purposes the pads are represented as LEDs).

image2 1024x894

Design the System

Before you begin implementing the code behind, make sure you sign up for a free PubNub account, as you'll need your publish/subscribe keys to send information across the PubNub Network.

Enable SSH

Secure Shell protocol (SSH) allows users to remotely access their RPi terminals from their computers over WiFi. If supplemented with GitHub, users can push code from their computers to a remote repository, SSH into the Pi terminal, and pull the code wirelessly. This allows for a quicker and smoother development process.

To enable SSH on your RPi, follow the simple and quick instructions.

Download Device Libraries and Dependencies

For our devices, you need to operate an output voltage of 1 or 0 from the RPI to turn things on. Conversely, the sensors give the RPi an input voltage of 1 or 0, depending on whether it is wet or dry. Both of these functions require the use of the RPi’s GPIO pins.

Since you’ll be coding in Python, it will be useful to install the GPIO Zero library, which will allow you to make simple function calls to activate or read in the pins.

NOTE: Remember that these libraries must be installed onto the RPi by SSH-ing into your device and running the commands below.

sudo apt install python-gpiozero

Build Your App with PubNub

The full code for this project is located in this repository for reference. Create a python script to interface our sensors to the internet. Open up a new document in your favorite text editor and import the libraries and other dependencies to enable the devices to communicate on the PubNub Network.

#---------------Library Setup----------------#
import pubnub
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub
from pubnub.callbacks import SubscribeCallback
from pubnub.enums import PNOperationType, PNStatusCategory
 
from gpiozero import Button, LED
from time import sleep
 
#--------------------------------------------#
 
 
 
 
#----------------PubNub Setup----------------#
pnconfig = PNConfiguration()
pnconfig.subscribe_key = "YOUR SUBSCRIBE KEY"
pnconfig.publish_key = "YOUR PUBLISH KEY"
pnconfig.ssl = False
pubnub = PubNub(pnconfig)
#--------------------------------------------#

You need to tell the Raspberry Pi which devices are connected to which of its pins:

#------------Sensor Declarations-------------#
#lamp is connected to GPIO4 as an LED
lamp = LED(4)
 
#door sensor is connected to GPIO3 as a Button
door_sensor = Button(3)
#light sensor is connected to GPIO14 as a Button
light = Button(14)
#--------------------------------------------#

NOTE: The lamp is declared as an LED as you want to control it as if it were a simple LED. The sensors are initialized as buttons as they output a constant active signal in the same way a button does when held down or pressed. This is the magic of the GPIO Zero library as it is effortless to interface with sensors and devices.

You should also create a counter variable to let yourself know how many times our door has been opened:

#door counter
doorCount = 0

In order to make sure that our IoT lamp can communicate with a client, you need to enable PubNub’s two-way pub/sub capability. To make sure you can receive messages, you need to add a listener to handle the incoming messages and declare a subscription to listen in on a particular channel.

class MySubscribeCallback(SubscribeCallback):
    def status(self, pubnub, status):
        pass
        # The status object returned is always related to subscribe but could contain
        # information about subscribe, heartbeat, or errors
        # use the operationType to switch on different options
        if status.operation == PNOperationType.PNSubscribeOperation \
                or status.operation == PNOperationType.PNUnsubscribeOperation:
            if status.category == PNStatusCategory.PNConnectedCategory:
                pass
                # This is expected for a subscribe, this means there is no error or issue whatsoever
            elif status.category == PNStatusCategory.PNReconnectedCategory:
                pass
                # This usually occurs if subscribe temporarily fails but reconnects. This means
                # there was an error but there is no longer any issue
            elif status.category == PNStatusCategory.PNDisconnectedCategory:
                pass
                # This is the expected category for an unsubscribe. This means there
                # was no error in unsubscribing from everything
            elif status.category == PNStatusCategory.PNUnexpectedDisconnectCategory:
                pass
                # This is usually an issue with the internet connection, this is an error, handle
                # appropriately retry will be called automatically
            elif status.category == PNStatusCategory.PNAccessDeniedCategory:
                pass
                # This means that PAM does allow this client to subscribe to this
                # channel and channel group configuration. This is another explicit error
            else:
                pass
                # This is usually an issue with the internet connection, this is an error, handle appropriately
                # retry will be called automatically
        elif status.operation == PNOperationType.PNSubscribeOperation:
            # Heartbeat operations can in fact have errors, so it is important to check first for an error.
            # For more information on how to configure heartbeat notifications through the status
            # PNObjectEventListener callback, consult <link to the PNCONFIGURATION heartbeart config>
            if status.is_error():
                pass
                # There was an error with the heartbeat operation, handle here
            else:
                pass
                # Heartbeat operation was successful
        else:
            pass
            # Encountered unknown status type
 
    def presence(self, pubnub, presence):
        pass  # handle incoming presence data
 
    def message(self, pubnub, message):
#message handler for Lamp commands
        #Turn the lamp on if client receives the message “ON”
        if message.message == 'ON':
        	lamp.on()
              #let your subscriber client know that the lamp has been turned off
        	pubnub.publish().channel('ch1').message("lamp has been turned on").async(publish_callback)
        	sleep(3)
        #Turn the lamp on if client receives the message “OFF”
        elif message.message == 'OFF':
        	lamp.off()
              #let your subscriber client know that the lamp has been turned off
        	pubnub.publish().channel('ch1').message("lamp has been turned off").async(publish_callback)
 
 
 
 
pubnub.add_listener(MySubscribeCallback())
#make sure to subscribe to the channel of your choice. In this case, we #chose to create a channel called “ch1” to publish to
pubnub.subscribe().channels('ch1').execute()

Take note of the message event handler. Any time your program receives a message from our application client, you open up the message using message.message. You then create event handlers with if statements to either turn the lamp on or off with the GPIO command .on() or .off().

Lastly, notice that when a message is published back to the client, the user is informed that you have completed their request. In this case, you let the client know whether the lamp is on or off.

This part is optional (since you are not using it for this program), but you can create a publisher callback to execute a function every time you publish a message.

def publish_callback(result, status):
    pass
    # Handle PNPublishResult and PNStatus

The last part of the program is going to constantly check the sensor inputs to see if the sensors detect anything. You can achieve this by creating a main while the loop repeatedly checks the inputs: while True:

Within the main while loop, you can create sub-while loops to poll the sensors specifically. Since you initialized the sensors as Buttons from the GPIO Zero library, you must call the function .is_held.

Although you are not using a button, the sensors act as if they were buttons as they simulate the same signal of holding down a button, while they are active (detecting something)

#polling loop to check if the door sensor is on
while door_sensor.is_held:
      #increment the door counter to count how many times the door has been opened
  doorCount = doorCount + 1
  door = "door has been opened: " + str(doorCount) + "times"
  pubnub.publish().channel('ch1').message(door).async(publish_callback)
 
 
door = "door is closed"
pubnub.publish().channel('ch1').message(door).async(publish_callback)
 
#polling loop to check if the lights are on
while light.is_held:
  pubnub.publish().channel('ch2').message("lights are on").async(publish_callback)
 
pubnub.publish().channel('ch2').message("lights are off").async(publish_callback)
 
sleep(3)

Here you check if the sensor is active. If so, publish a message back to the client letting it know whether the sensor is on or off.

How to Upload Your Code

In order to upload your code to your Raspberry Pi, you should always commit your code to your repository and then pull it to your Raspberry Pi.

Open up your terminal and enter your working directory. Then commit your code to the cloud using these commands.

git add .
git commit -m "updates"
git push

SSH into your RPI and cd into the proper directory.

ssh pi@<YOUR IP ADDRESS>
cd <your directory>

Pull the code from the cloud and run it.

git pull
python <Your program>.py

Build a Client with PubNub

Next, you need to build a client script that will allow you to use a mobile phone or computer to send and receive data to our sensors. To do this, you will need to create an HTML file that will use buttons to publish commands to the RPI and Text boxes to retrieve data from the RPI.

Start with a blanked HTML script like this:

<!DOCTYPE html>
<html>
  <body>
    <script>
    //your Code Here
    </script>
  </body>
</html>

Create two buttons to publish ON or OFF commands to our RPI.

<button type="button" onclick="publish('ON')">Lamp ON</button>
<button type="button" onclick="publish('OFF')">Lamp OFF</button>

Create an ID tag to later inject the light sensor data we subscribe from the RPI.

<p id="lights">Lights are on?</p>

Import the PubNub JavaScript SDK so you can actually enable pub/sub capabilities.

<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.20.2.js"></script>

Set up the channel using your given pub/sub keys.

<script>
var pubnub = new PubNub({
  publishKey : 'pub-c-2d8f55f6-daa7-467b-923b-6a1e6570c9fc',
  subscribeKey : 'sub-c-1575c412-2116-11e8-a7d0-2e884fd949d2',
  });
  function publish(a){
    var publishConfig = 
    {
      channel : "ch1",   //Your publishing channel name
      message : a
    };
    pubnub.publish(publishConfig, function(status, response){
      console.log(status, response);
    });
    
  }

Lastly, we need to listen in on the channel the RPI is publishing our light sensor data. We can instantiate a listener with this block of code:

pubnub.addListener({
        message: function(m) {
            // handle message
            var channelName = m.channel; // The channel for which the message belongs
            var channelGroup = m.subscription; // The channel group or wildcard subscription match (if exists)
            var pubTT = m.timetoken; // Publish timetoken
            var msg = m.message; // The Payload
            var publisher = m.publisher; //The Publisher
            document.getElementById("lights").innerHTML = msg;
            console.log(msg)
        },
        presence: function(p) {
            // handle presence
            var action = p.action; // Can be join, leave, state-change or timeout
            var channelName = p.channel; // The channel for which the message belongs
            var occupancy = p.occupancy; // No. of users connected with the channel
            var state = p.state; // User State
            var channelGroup = p.subscription; //  The channel group or wildcard subscription match (if exists)
            var publishTime = p.timestamp; // Publish timetoken
            var timetoken = p.timetoken;  // Current timetoken
            var uuid = p.uuid; // UUIDs of users who are connected with the channel
        },
        status: function(s) {
            var affectedChannelGroups = s.affectedChannelGroups;
            var affectedChannels = s.affectedChannels;
            var category = s.category;
            var operation = s.operation;
        }
    });
    pubnub.subscribe({
        channels: ['ch2'],
        
    });
</script>

Take note that you subscribed to ch2. This is because you want a dedicated channel for the light sensor data so that you do not need to actually differentiate the data from other sensors. If you forgot to publish to a dedicated channel in the Application process before, make sure you go back and do so.

Once you save your script, open the file up in a web browser and you should have something like this:

image7 1024x431

You have now completed implementing three simple smart home devices on a Raspberry Pi! Test your code out by ssh-ing into your Raspberry Pi to run your python code and then interact with your client program. You should be able to control your smart lamp with the two buttons as well as see text prompts if your door is open or your lights are on. You've successfully created a smart home system using connected devices communicating with PubNub.

If you would like to learn more about how to power your IoT applications and smart home systems, take a look at our IoT resources.

If you have any other questions or concerns, please feel free to reach out to devrel@pubnub.com.

More from PubNub

NPP and HIPAA: Notice of Privacy Practices Definition
Healthcare CategoryJan 6, 20235 min read

NPP and HIPAA: Notice of Privacy Practices Definition

A Notice of Privacy Practices (NPP) is one of the requirements of HIPAA and helps patients understand their personal data rights.

Michael Carroll

Michael Carroll

HIPAA Violation Examples
Healthcare CategoryJan 5, 20236 min read

HIPAA Violation Examples

HIPAA violations can be financially expensive and devastating to a brand. Examine some examples of HIPAA violations, and learn...

Michael Carroll

Michael Carroll

HIPAA Technical Safeguards: How To Protect Sensitive Data
Healthcare CategoryJan 5, 20236 min read

HIPAA Technical Safeguards: How To Protect Sensitive Data

HIPAA covered entities must follow the five technical safeguards to achieve HIPAA compliance and prevent data corruption.

Michael Carroll

Michael Carroll