Build a Voice Controlled Outlet with Raspberry Pi and Swift
Ever wish you could control all of your electronics with a simple command, or just the push of a button? Well, armed with a Raspberry Pi, a smart phone, and PubNub’s Global Data Stream Network, you can make that dream a reality. Get ready to use your smart phone to be able to control outlets in your house from anywhere in the world.
In this tutorial, I’ll show you how to use a Raspberry Pi to control a power outlet using an RF transmitter, a process facilitated by commands sent via PubNub. Then, I’ll show you how to build a very simple app using Swift, Apple’s programming language, to send those commands with either your voice or the press of a button. This tutorial will assume you’ve already set up your Raspberry Pi with Raspbian or a comparable operating system. If you haven’t, no worries, just check out the first section of this tutorial on creating a Raspberry Pi Smart Home entitled “Setting Up the Raspberry Pi” and you’ll be brought up to speed.
Required Hardware
- Raspberry Pi 2, Model B
- USB keyboard
- USB mouse
- External monitor
- HDMI Cable
- Micro-SD card
- Micro-SD card adapter
- 2.5A power supply
- USB WiFi dongle
- Solderless breadboard
- Etekcity Remote Control Outlet
- SMAKN 433Mhz RF Transmitter and Receiver Kit
- Male/female jumper wires
RF Transmissions
In this project you’re going to use an RF Transmitter to send codes to an Etekcity outlet, a job that was previously done by a remote. This process requires wiring the transmitter and the receiver to the Raspberry Pi, finding the codes the remote uses, and transmitting those codes to control the outlet without the remote.
Hardware Setup
Wiring the transmitter and receiver is a fairly simple process. On the transmitter (the component with 3 pins), connect DATA to GPIO 17, VCC to 5V, and GND to Ground. On the receiver (the component with 4 pins), the left pin, when viewed face-up with the pins facing down, should be connected to 5V, the second pin from the left to GPIO 21, and the right pin to Ground. You’re ready to start using it!
Using RFSniffer
To figure out the codes that you need to send, you first need to install WiringPi. Navigate to the command line on your Raspberry Pi and download the software using git.
$ sudo apt-get install git
$ git clone git://git.drogon.net/wiringPi
To finish the installation, type the following commands.
$ cd wiringPi
$ ./build
To make sure it worked, type gpio -v into the command line, and you should see details about your Raspberry Pi printed to the console. To use RFSniffer, type the following command.
$ sudo /var/www/rfoutlet/RFSniffter
Now when you press buttons on the remote that came with the outlet, you should see numbers appear on the console. Record the five-digit numbers that appear when you press off and on – you’ll need them to toggle the outlet.
Testing the Codes
To make sure your RF Transmitter is working properly, try turning the outlet on and off using the command line. Just type the code below, replacing [code] with either of your five-digit numbers.
$ sudo /var/www/rfoutlet/codesend [code]
If the light on the outlet turned on and off based on your commands, congratulations! You’re right on track. If not, you’ll need to go back and make sure everything is properly installed, then try again.
The Raspberry Pi Script
Now that you know your RF transmissions are working properly, it’s time to write a Python script to send the codes for you, based on messages that will be sent using PubNub.
Script Setup
Before you can start coding with PubNub, you’ll need to make sure all the libraries you need are installed and up to date. Open up your terminal by clicking on the black icon in the top left corner of your screen, then type the following commands to update and install the necessary libraries.
sudo apt-get update
sudo apt-get install python-dev python-pip
sudo pip install pubnub
Then, at the top of your script, include the necessary libraries.
import os import sys from pubnub import Pubnub
Finally, to initialize PubNub, just input your publish and subscribe keys and define your channel.
pubnub = Pubnub(publish_key='your-publish-key', subscribe_key='your-subscribe-key') channel = 'OutletControl'
Receiving PubNub Commands
To receive commands from PubNub, you first need to subscribe to your channel and define your callback and error functions.
def _callback(m, channel): def _error(m): print (m) pubnub.subscribe(channels=channel, callback=_callback, error=_error)
Next you should fill in your callback function to react to PubNub messages by turning the light on or off.
def _callback(m, channel): if m.get("outlet") == "on": os.system('sudo /var/www/rfoutlet/codesend [code]') if m.get("outlet") == "off": os.system('sudo /var/www/rfoutlet/codesend [code]')
And you’re done with the Raspberry Pi part! Time to move on to creating the app.
Creating the App
Now that you’ve set up the Raspberry Pi, you’re ready to build an app to control it. In this tutorial I’m going to show you how to do it using Swift, but it can easily be adapted for many different programming languages or mobile devices, just take a look at all the PubNub SDKs and pick one! The syntax will be different, but all you really need is a subscribe call to make it work.
Installing PubNub and SpeechKit
To install both PubNub and SpeechKit, you’ll need to use CocoaPods. There’s a great tutorial on the CocoaPods website to install and get started with pods. After you install the software, just follow the directions under Creating a New Xcode Project with CocoaPods to begin your project. Your podfile should look like this when you’re done.
target 'Outlet Control' do source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! pod ‘PubNub’, '~> 4.4.1' pod 'SpeechKit', '~> 2.1' end
Initializing PubNub in Swift
To use PubNub, you’ll have to initialize it in the AppDelegate.swift file using your publish and subscribe keys.
class AppDelegate: UIResponder, UIApplicationDelegate, PNObjectEventListener { var window: UIWindow? var client : PubNub? override init() { let configuration = PNConfiguration(publishKey: "your-publish-key", subscribeKey: "your-subscribe-key") client = PubNub.clientWithConfiguration(configuration) super.init() client?.addListener(self) } ...
Building the User Interface
The UI for this project is fairly simple, though you’re free to add some more flair if you’d like. To control the outlet, all you really need is a switch. I also included a button to use with Speechkit to that the outlet can be controlled using voice commands. To create the components, open Main.storyboard in Xcode. In the toolbar on the right side side of the screen, show the object library by clicking on its icon.
Drag a button and a switch onto the storyboard and label them appropriately. Customize the page to your liking using different colors, fonts, and spacing. Here’s a peek of my finished product.
Finally, you need to link your UI elements to your code. Make sure you’re using the assistant editor by selecting the appropriate icon at the top of the page. You should have both Main.storyboard and ViewController.swift visible. In ViewController.swift, import UIKit, PubNub, and SpeechKit at the top of the program.
import UIKit import PubNub import SpeechKit
Hold the control key while you click the Listen button on your storyboard, then drag it to your ViewController class. Name the button, but don’t change any of the other settings. Do the same for your switch, so you can easily reference it later. Now control-drag the button and the switch again, but this time change Connection to Action. This will allow you to create functions that are only called when each button is pushed, which you’re now ready to do.
Using SpeechKit
Let’s start with the Listen button. You’ll want to be able to push it, say a command, and have the app interpret that command and send a corresponding message to your channel. This is actually pretty simple using SpeechKit from Nuance Developers. They give you all the functions you need, you just need to include them in your app and tweak them for your needs. First, you’ll need to create an account with Nuance. It’s easy to do through the Nuance website, plus it’s free!
Once you’ve got all your credentials settled, you need to define the delegate in the class header.
class ViewController: UIViewController, SKTransactionDelegate { … }
Now, in the ListenClicked function, define the session with your various tokens.
@IBAction func ListenClicked(sender: AnyObject) { ListenButton.setTitle("Listening", forState: .Normal) let session = SKSession(URL: NSURL(string: "your-string"), appToken: "your-token") session.recognizeWithType(SKTransactionSpeechTypeDictation, detection: .Long, language: "eng-USA", delegate: self) }
Next you’ll need to create a transaction function inside of your ListenClicked function for SpeechKit to use to interpret speech. You can choose any keywords you like to control the outlets, but I chose “off” and “on” for simplicity.
func transaction(transaction: SKTransaction!, didReceiveRecognition recognition: SKRecognition!) { if recognition.text.lowercaseString.rangeOfString("on") != nil { print("Found \"on\" in speech") } if recognition.text.lowercaseString.rangeOfString("off") != nil { print("Found \"off\" in speech") } }
Now when you click the Listen button in your app, you’ll see a message on the console when you say “off” or “on.”
Sending PubNub Messages
It’s time to start streaming information between the Raspberry Pi and the app using PubNub. To do this, you just have to publish messages to your channel when either the switch is pressed or SpeechKit detects your commands. First you’ll need to link your initialization in AppDelegate to ViewController.
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
Next, write publish functions that correspond to pressing the switch.
@IBAction func Switch(sender: AnyObject) { if OnOffSwitch.on { appDelegate.client?.publish(["outlet":"on"], toChannel: "OutletControl", compressed: false, withCompletion:{(status)->Void in if !status.error { } else{ print("Publishing Error (On)") } }) } else { appDelegate.client?.publish(["outlet":"off"], toChannel: "OutletControl", compressed: false, withCompletion:{(status)->Void in if !status.error { } else{ print("Publishing Error (Off)") } }) } }
Now just put a publish function in the “if” statements you made for the Listen button and you’re good to go!
Testing the Setup
To test your app and Raspberry Pi setup, make sure your script is running on the Raspberry Pi, and upload the app to your favorite mobile device. You should be able to toggle your outlet on and off by using either the switch, or by pressing Listen and saying either “off” or “on.” Ta-da! Now you can control the outlet from anywhere, with just your voice or the simple tap of a button.
Next Steps
Congratulations! You’ve successfully put together an outlet that can be controlled remotely from your phone. Hopefully you’ve also learned a little bit about Raspberry Pi, Swift, and PubNub along the way. Now you’re ready to tackle other projects using Swift, like this AppleTV controlled simulated Smart Home, or this real-time radio station. If you want to explore more with Raspberry Pi, check out these cool tutorials on building a heart rate monitor or a dashboard camera. Whatever you choose to do, have fun, and good luck!