IoT Lock - Control with a Tweet
Let’s take what we did in Internet Lock - Part 1, and add a program to control it in real time from Twitter!
Disclaimer: This security-related project is just that: a project. This is not intended to be a fully-featured nor robust home security solution. Use your own judgment when applying this project to securing your belongings, property, etc. By doing this project, you accept all risk and Onion cannot be held responsible for any damages or misuse.
Overview
Skill Level: Intermediate
Time Required: 30 minutes
The code will be written in Python and we’ll be making use of Twitter’s Streaming APIs to grab Tweet data. Specifically, the code uses the Tweepy library to manage authentication and keeping a persistent HTTP connection to Twitter.
Same as before, the code used to handle this setup can be found in the iot-door-lock repository on GitHub.
Lock Access Rules
First, this app will be listening for new tweets from the users you specify in the configuration file. Please note that all public tweets will be received over the Internet by your Omega when the main script is running.
By default, the Omega is configured to change the state of the lock when it detects a tweet from an authorized user with a corresponding hashtag. The list of allowed users and hashtags for each command are configured in a separate JSON file, config.json
.
The default hashtags that correspond to lock actions are:
Hashtag | Lock Action |
---|---|
#lock | Program the Relay to set the lock to locked |
#unlock | Program the Relay to set the lock to unlocked |
#toggle | Unlock, wait 5 seconds, lock again (Does nothing if lock is already unlocked) |
Some examples of authorization are shown below (all of the command hashtags follow the same rules):
Event | Lock Response |
---|---|
@authorizedUser1 posts a status containing #unlock |
Unlock |
@authorizedUser2 replies to a status and includes #toggle |
Toggle (briefly unlock, and then lock again) |
@authorizedUser2 retweets a status from @authorizedUser1 that contains #lock |
Lock |
@unauthorizedUser1 posts or retweets a status containing #toggle |
None |
@unauthorizedUser2 posts retweets a status from @authorizedUser1 containing #unlock |
None |
Note: The lock will respond to the first command hashtag it finds in each status, so posting “#lock
#unlock
” will activate the lock.
Ingredients
Unlike Part 1, the dependencies for the Python Twitter software requires more space than is available on the Omega2 standard model by default. You will either have to boot from external storage or use an Omega2+ instead.
We will be using the same components and setup as in the first part:
- Onion Omega2 or Omega2+
- Any Onion Dock that supports Expansions: Expansion Dock, Power Dock, Arduino Dock 2
- Onion Relay Expansion
- An electric solenoid lock
- We recommend a simple power locking, normally unlocked lock so you don’t get locked out when there’s no power.
- Appropriate DC power supply for your lock
- We found a 12V 1A DC power supply to be compatible with most locks
Here’s what our list looked like - minus the mounting tools and parts.
Step-by-Step
Follow these instructions to control the smart lock from Twitter on your very own Omega!
1. Prepare
You’ll have to have your Omega2 ready to go, complete the First Time Setup Guide to connect your Omega to WiFi and update to the latest firmware.
2. Complete Part 1 of the Project
This project builds on the first part of the IoT Lock project. If you haven’t already completed the first part, go back and do it now!
3. Install Dependencies
Connect to the Omega’s command line and run the following commands:
opkg update
opkg install python-pip
pip install --upgrade setuptools
pip install tweepy
4. Create a Twitter Application
We’ll need to create a Twitter Application in order to be able to use Twitter’s APIs to grab Tweets. Specifically, our code needs the following information:
- an API Key
- an API Secret
- an Access Token
- an Access Token Secret
in order to authenticate with Twitter before we can use the APIs.
- If you don’t have a Twitter account, create one now.
- Head over to https://apps.twitter.com and sign in with your Twitter handle
- Fill in the form details for your application. Twitter app names must be unique globally, so try calling it
omega-ABCD-door-lock
, where ABCD are the 4 digits in your Omega’s hostname.
- Read and agree to the Twitter Developer Agreement and hit Create your Twitter application.
Note that your Twitter account must have an associated mobile phone number before Twitter will allow you to create an application!
- Your Application is now created!
- Head over to the Keys and Access Tokens tab to grab the info we need
- Scroll down to the section called “Your Access Token”, and click “Create my access token”.
We will be using the 2 pairs of keys and secrets to authorize our app to connect to Twitter, so copy and paste or write them down somewhere for later.
5. Edit the Configuration File
Open the config.json
file and edit or paste in the following information:
config.json | Value |
---|---|
consumerKey | Consumer Key in the Twitter application menu |
consumerSecret | Twitter Consumer Secret |
accessToken | Twitter Access Token |
accessTokenSecret | Twitter Access Token Secret |
allowedUsers | A comma-separated list/array of screen names who will have access to your lock. eg.: ["@john_smith", "@jane_doe"] |
hashtags | Customize the hashtag you want for each action. The defaults are #lock , #unlock , and #toggle . |
If you trust them, you can add friends or family to the list of allowed users.
6. Running the Project
Navigate to the repo directory and run:
python tweetLock.py
The script will then run forever, listening for new tweets until you exit by pressing Ctrl-C
.
Now try tweeting from some of the allowed accounts and include one of the hashtags you configured. You should see your lock reacting very quickly!
Tell your friends to try it out too!
7. Rate Limiting
The Twitter Streaming API that pushes new tweets to the Omega limits the amount of new sessions you can initiate within a certain period of time. If you restart the program too often in a short window of time, you will receive a 420 error. You will see a warning on the command line, and the program will automatically disconnect and retry according to Twitter’s recommended backoff policy; see the Rate Limiting section on Twitter’s documentation.
The rate limiting criteria are not made public, so we recommend playing it safe and relaxing for about 5-10 minutes each time you need to restart the script.
Note: Too many connection attempts may result in your IP being banned from connecting to Twitter!
8. Running the Program on Boot
We can automate this project to run when the Omega is turned on, and we can also make it run in the background so you can use the Omega for other things while it’s running! To do this, we’ll place a script in /etc/init.d
.
In the repo folder, make the etc/init.d/tweet-lock
file executable, copy it to /etc/init.d
, then enable it to run on boot:
cd etc/init.d
chmod +x tweet-lock
cp tweet-lock /etc/init.d
/etc/init.d/tweet-lock enable
Wait for 5-10 minutes, reboot the Omega, and you will automatically be able to tweet at your lock again!
The
/etc/init.d/tweet-lock
script registers the IoT Lock Python script as a service withprocd
, the process management daemon of the system.procd
then ensures that the process gets started at boot and continues to run until the service is disabled.
Code Highlight
This project uses the Twitter Streaming API, made easily accessible by the Tweepy library. Streaming, as opposed to using the REST API, lets Twitter push data such as new statuses or direct messages immediately after they happen in real-time. This eliminates the overhead of repeatedly polling Twitter for new information; it’ll get sent to us as it happens.
When opening a stream, you must specify some way to filter the incoming tweets. This is because thousands of tweets are sent every second on average; that’s a lot! The two most common ways of doing this are by:
- following particular users
- tracking keywords
Here we use the first method by only receiving tweets from our list of authorized users.
The streaming functions have been further abstracted by the StreamListener
and TwitterApp
classes in twitterHelper.py
. Any class that is used to receive and process tweets must extend the tweepy.StreamListener
class by redefining its callback methods, such as on_status()
and on_error()
. These functions are called when an event such as a new status occurs. They do nothing by default, so you need to tell them what to do!
For full details on the Tweepy library, visit the documentation page.