Thanks!
You've just made my office lamp blinks. šŸ’”
How does that happen?

The requirement is fairly simple: we need to send a signal from anywhere in the world to the internet-enabled device in order to make it behave as we want. We are not intended here to implement large-scale solution and complicate things.

There are technically many ways to meet our requirement ā€“ from building the solution from scratch up to using one of off-the-shelfs cloud services. But we donā€™t care about them. We just need to experiment with the ā€œinternet of thingsā€: how to control a device from anywhere in the world.

This article is not for you if you want an enterprise-level solution for your IoT project, in case you have thousands of devices to control, with critical requirements and several security concerns.



The Hardware

Iā€™m going to use Raspberry PI for easiness. Although you can use your internet-enabled controller (Arduino with ESP module, NodeMCU, WeMosā€¦ etc).


The Software

1. Web-based user interface

A simple user interface for the end-user in order to control the device from. I built it for you.

2. PubNub

Pubnub is used to deliver messages between our control unit (the web-based user interface) and the device. You can think of it as a cloud-service that provide publish-subscribe messaging pattern.

In this pattern, thereā€™s a publisher who can publish / send messages through certain channels. And a subscriber who can subscribe / listen to those channels. Whenever a message is published through channel x, all the subscribers of channel x will receive the message.

In our case:

  • The user publishes (sends) messages through a channel named commands.
  • The Raspberry PI is interested in subscribing for, (receiving), messages from the commands channel.
  • Every message sent through the commands channel, is received from the Raspberry PI. And then the Raspberry PI is able to behave based on the received message.

Create PubNub account

You need to have PubNub account, itā€™s free. Create an account, then create an app, and keep the credentials (subscribe and publish keys) with you.




Setting up PubNub with Raspberry PI

Since I’m using Raspberry PI, Iā€™m going to use the Python SDK for PubNub, You can use the suitable SDK for your controller..

In your Raspberry PI you can install it from the command line:

pip install 'pubnub>=4.4.0'

Now we need to subscribe for all the messages that are sent through a channel called messages, the following code should configure PubNub client based on the constants SUBSCRIBE_KEY (which is available in your account) and CHANNEL (the name of the channel).


    import sys
    import time
    sys.path.append('/usr/local/lib/python3.7/site-packages')
    
    from pubnub.pnconfiguration import PNConfiguration
    from pubnub.callbacks import SubscribeCallback
    from pubnub.pubnub import PubNub
    
    SUBSCRIBE_KEY = 'sub-c-fee6fbae-4fb6-11ea-80a4-42690e175160'
    CHANNEL = 'messages'
    
    # Setting up PubNub
    pnconfig = PNConfiguration()
    pnconfig.subscribe_key = SUBSCRIBE_KEY
    pubnub = PubNub(pnconfig)
    
    pubnub.add_listener(SubscribeCallback())
    pubnub.subscribe().channels(CHANNEL).execute()
    
    class SubscribeCallback(SubscribeCallback):
        def message(self, pubnub, message):
            print(f'Received message: {message.message}')
            
            if message.message == 'blink':
                blink()
    
    
    def blink():
        print('I should blink.')

Now whenever you run this code (from an IDE or using the command line python pubnub.py), each message sent from PubNub over the messages channel will be printed out.




Setting up PubNub with Web client

Here’s a Web-based user-interface of which we can control the Raspberry PI from. PubNub provides many SDKs for variety of platforms, you can integrate it with any platform you like.

However, I built the web client for you, you can find the source code in the Github repo (client.html). Or you can just use the one below:

Insert your publish and subscribe keys in the first two fields, then insert the channel name of which youā€™d like to send the messages through.

The name of the channel should exactly match the one the Raspberry PI subscribes to.




Test it

If everything above is implemented, once you you hit the Send button, the message should be received on the Raspberry PI side. Nothing fancy for the time being, it only prints a message to the console.




Blinking LED

Letā€™s make a physical reaction to the received message. The simplest thing is to connect an LED and make it blinks. You may, in the future, replace the LED with any other ā€œsystemā€; it could you an espresso machine making a cup of coffee, your room lamp turning it on and off.. or any controllable device.

Hardware connection

The Raspberry PI comes with many pins you can use (GPIO). We are interested in connecting the LED to the negative pin (the ground, pin 39), and a positive pin (high voltage: pin 40 / GPIO 21).

Source: https://www.raspberrypi.org/documentation/usage/gpio/

Letā€™s get back to the Python code and make the changes to make the LED blinks. Iā€™m going to use a library called GPIO Zero in order to setup the LED connections. First we need to import the LED module, and the sleep function:

from gpiozero import LED

from time import sleep

Letā€™s define an LED object, as we mentioned above, weā€™re using the pin GPIO 21.

led = LED(21)

Now instead of printing a message, letā€™s replace it with the following code:



led.on()  # turn on the led 
sleep(1)  # then wait 1 second
led.off() # then turn it off

If the received message is blink, the LED will blink.




How to improve?

  • Telemetry data

    What we have done is sending commands from control unit to the device. But what if we want to send telemetry data from the device to the control unit? The same concept, reversed. The Raspberry PI publishes message over certain channel and the control unit subscribes to it. Once a message is received, itā€™s your choice, for example, to save it to a database or to display it to the users in real-time.

  • Control high-power devices

    What if you want to control high-power devices, like a room lamp? This could be implemented using a relay.

  • Customized control unit

    You can build the control unit on any platform PubNub supports. I choose the web since itā€™s accessible from any device. You can build your own for mobile applications, or to enhance the web client further with advanced user interface that satisfies your needs. And you can deploy the it to be accessible from anywhere. Zeit or Netlify are excellent choices.




Last month, I tweeted a video (and published it on Reddit) showing an LED blinks whenever someone visits my website. Several people reached out asking how. It’s the same implementation of the above, I only send the message to the Raspberry PI when the website is loaded.