In this blog post I show how you can quickly setup and implement a control software for your switches at home with some modern JavaScript stuff. This project should primarily help me to get more in touch with these kinds of freaky scripting and this is maybe helpful for other Java Developers or people who want to play around with the Raspberry Pi. So I decided to share it with you. There is no line of old-fashioned Java code here, but maybe some really technical C++-code ;-). Please note, that this is not a tutorial for the usage of the frameworks. The tutorials that you can find in the internet are very good and I don’t want to repeat all of the basic fundamentals in this post. The complete code is also available at Github .
Prerequisites
You need the following Hardware to do it:
- Raspberry Pi
- 433 MHz Sender
- SD Card with an installed Raspian “wheezy” operating system
- 4 Jumper Cables
- Some RC switches. This will most likely work with all popular low cost power outlet switches which you can find in the DIY markets (e.g. Intertechno, Elro, Rev, etc.). For an incomplete list of supported devices refer to this link
.
When you just want to play around with AngularJS and you have no Raspberry Pi, then you can skip the first steps and just use the mock implementation of the REST server at apiary.io .
Install the Raspberry Pi Hardware
Before we can start hacking we need to connect the 433 MHz Sender to the GPIO pins of the Raspberry Pi like in the following picture:
PIN 1 GND -> PIN 6 (GND)
PIN 2 Data in -> PIN 11 (GPIO17)
PIN 3 Vcc -> PIN 2 (5V)
PIN 4 -> Antenna
Install the Raspberry Pi Software
It’s easier to access the Pi over password-less ssh to setup the software environment . Make sure that you activated ssh in the raspberry-config and it’s up and running. When you don’t want to use ssh, than just skip this step.
1ssh-keygen 2cat ~/.ssh/id_rsa.pub | ssh pi@raspberrypi "mkdir ~/.ssh; cat >> ~/.ssh/authorized_keys"
For easier handling during development I installed a Bonjour service on the Raspberry Pi. It’s now possible to directly access the Pi with the Finder (Mac required ;-)).
Install wiringPi
Please follow the instructions here to install the library for accessing the GPIO pins of the Pi or just run the following commands on the Pi:
1sudo apt-get install git-core 2sudo apt-get update 3sudo apt-get upgrade 4git clone git://git.drogon.net/wiringPi 5cd wiringPi 6./build
Install rcswitch-pi
The library was originally developed for the Arduino and was then ported to the Raspberry Pi. In the mean time the original library was extended with support for a special kind of switches from the company Rev . I forked the rcswitch-pi repo and added this functionality also to the Pi-lib, because I have them at home and also want to control these devices. Although I have made a pull request , which is not merged actually.
To install my version of the library just clone the git repo and compile the source code:
1git clone https://github.com/denschu/rcswitch-pi 2make
The following steps are highly dependent on the switches you have at home. To find out which protocol to use please have a look a this link . For my Elro devices I use this command to turn the first switch on:
1#Turn Elro switch 1 on (Housecode="11111" -> means all dips on) 2sudo ./send 11111 1 1
For my Rev-devices I added a sendRev-command to the Repo, which you can also use directly:
1#Turn Rev switch 1 with Group B on 2sudo ./sendRev B 1 1
Ok, at this point the basic stuff works and we are able to control our radio-controlled devices through the shell 🙂 Cool.
Install node.js
The setup of node.js is very easy, but takes some time. So start the compile process and get some coffee 🙂
Get and extract it:
1cd /usr/src 2sudo wget http://nodejs.org/dist/v0.8.16/node-v0.8.16.tar.gz 3sudo tar xvzf node-v0.8.16.tar.gz 4cd node-v0.8.16
Compile it:
1sudo ./configure 2sudo make 3sudo make install
Test it:
1sudo make test
Don’t worry, when not all of the tests will pass. For more infos and basic testing of the installation check out this really good tutorial .
Start hacking – Create the REST Server
Design the API
For the design and documentation of a REST API I recommend apiary.io . It’s a web-based tool and brings you really cool features out-of-the-box, e.g. a Mock Server, an Inspector, a Test-Tool, etc. Actually it’s in beta and there are outstanding modifications on the API Blueprint Format. They want to switch to the more readable Markdown which is also used by Github.
I have designed the API completely with apiary.io. You can find it here:
http://docs.rcswitch.apiary.io/
Do some basic testing with curl
Make a GET-Request against the apiary-Mock-Server:
1curl -i -X GET http://rcswitch.apiary.io/switches
Implement the REST Server with Express
In the previous step we designed the REST API. Now it’s time to start with some JavaScript hacking. The framework Express works on top of node.js and is a very easy possibility to create a small web application or in this case a REST-Server which delivers and accepts JSON-data.
That’s the basic code to setup a http server with Express (server.js):
1var express = require('express'),
2 api = require('./routes/api');
3var app = express();
4
5app.configure(function(){
6 app.use(express.bodyParser());
7});
8
9// JSON API
10app.get('/switches', api.switches);
11app.get('/switches/:id', api.switch);
12app.post('/switches', api.addSwitch);
13app.put('/switches/:id', api.editSwitch);
14app.delete('/switches/:id', api.deleteSwitch);
15
16// Start server
17app.listen(8000);
18console.log("Server running at http://127.0.0.1:8000/");
In a separate file (api.js) we call the previously installed rcswitch-library (this is only a snippet – the full source code is on Github ):
1var util = require('util')
2var exec = require('child_process').exec;
3
4// GET
5exports.switches = function (req, res) {
6 console.log('Getting switches.');
7 var switches = [];
8 res.json(data);
9};
10
11// PUT
12exports.editSwitch = function (req, res) {
13 var id = req.params.id;
14 if (id >= 0 && id <= data.length) {
15 console.log('Switch Status of switch with id: ' + id + " to " + req.body.status);
16 var script = data[id].script;
17 var command = data[id].command;
18 switchStatus(script,command,req.body.status);
19 data[id].status = req.body.status;
20 res.send(200);
21 } else {
22 res.json(404);
23 }
24};
25
26function switchStatus(script, command, status){
27 var execString = script + " " + command + " " + status;
28 console.log("Executing: " + execString);
29 exec(execString, puts);
30}
To install the whole Server from my Github Repository run the following commands:
1git clone https://github.com/denschu/rcswitch-rest 2cd rcswitch-rest 3npm install 4node server.js
Configuration
In the file api.js you need to configure your devices which you want to operate through the REST Server. This is a minimal example configuration:
1var data = [ 2 { 3 "id": "0", "url": "/switches/0", "name": "Lamp 1", "script": "sudo /home/pi/rcswitch-pi/sendRev", "command": "B 1", "status": "0" 4 } 5 ];
Test it also with curl
The call to the local server should respond with the same structure like the mock server above.
1curl -i -X GET http://raspberrypi:8080/switches
Now, you can also switch the first device on through HTTP:
1curl -i -X PUT -H 'Content-Type: application/json' -d '{"status": "1"}' http://raspberrypi:8000/switches/0
The mock server is used by the AngularJS-Application per default, so you can play around with it without having a Raspberry Pi etc.
Create the GUI with AngularJS and Twitter Bootstrap
Ok, now the Server is finished and we can start to design the GUI. I used the CSS-Framework Twitter Bootstrap, because it’s very easy to create a responsive user interface with a minimal effort of time and knowledge about GUI-Design 😉
Let’s create a button:
1<div class="container"> 2 <table class="table table-hover"> 3 <tbody> 4 <tr> 5 <td> 6 <h2>Lamp 1</h2> 7 <div class="btn-group" data-toggle="buttons-radio"> 8 <button type="button" class="btn btn-success">On</button> 9 <button type="button" class="btn btn-danger" >Off</button> 10 </div> 11 </td> 12 </tr> 13 </tbody> 14 </table> 15</div>
Bootstrapping AngularJS
Angular Seed is basically a application template for a typical AngularJS web app. It helps you to bootstrap the development environment very quickly. It contains also some tests and a web-server to start hacking without the need to setup a complete infrastructure. To get a basic overview I can recommend the tutorial directly from AngularJS which is also based on the Angular Seed project template. Home.Pi was completely developed with the template. That is the main application definition:
1angular.module('homePiApp', ['homePiApp.filters', 'homePiApp.services', 'homePiApp.directives']).
2 config(['$routeProvider', function($routeProvider) {
3 $routeProvider.when('/', {templateUrl: 'partials/switches.html', controller: SwitchListCtrl});
4 $routeProvider.otherwise({redirectTo: '/'});
5 }]);
In a separate service (app/js/services.js) we call the existing REST API on apiary.io:
1var app = angular.module('homePiApp.services', ['ngResource']);
2
3var url = "http://rcswitch.apiary.io/switches";
4
5app.service('Switch', function($http) {
6 this.query = function() {
7 console.log("Returning Switches");
8 return $http.get(url).then(function (response) {
9 console.log(response);
10 return response.data;
11 });
12 };
13});
To make the static HTML Template from above more dynamic, just add some AngularJS magic:
1<div class="container"> 2 <table class="table table-hover"> 3 <tbody> 4 <tr ng-repeat="switch in switches"> 5 <td> 6 <h2>{{switch.name}}</h2> 7 <div class="btn-group" data-toggle="buttons-radio"> 8 <button type="button" class="btn btn-success" ng-click="turnSwitchOn(switch.id)">On</button> 9 <button type="button" class="btn btn-danger" ng-click="turnSwitchOff(switch.id)">Off</button> 10 </div> 11 </td> 12 </tr> 13 </tbody> 14 </table> 15</div>
To get the whole application up and running just clone the Github-Repo and start the web server for the AngularJS-Client:
1git clone https://github.com/denschu/home.pi 2cd home.pi 3./scripts/web-server.js
The application runs here: http://localhost:8080/app/index.html
When you want to test against your local REST server, then just replace the “url” with the adress of your web server in the services.js-file.
1var url = "http://raspberrypi:8080/switches"
Start the servers in the backround
To run the servers in the backround, then start them with nohup and delegate the output to a logfile. There are other possibilities available, for example Forever . Give it a try!
1nohup node server.js > /tmp/rcswitch-rest.log & 2nohup ./scripts/web-server.js > /tmp/homepi.log &
What’s next?
From my point of view I must say that the frameworks and technologies in the context of JavaScript improved a lot over the last years. There are a lot of other areas and tools to play around with, e.g.
- Grunt for build management
- RequireJS for dependency management
- Bower for package management on the client
- Yeoman
Maybe I will automate the build and deployment stuff with TravisCI and get the software running on a cloud platform like Heroku. There are also a lot of functional features in my brain. But let’s see. What do you think about it? Are that maybe technologies that you would use in your enterprise projects? I would appreciate any kind of feedback. Pull requests on Github are always welcome.
The Source Code
- REST Server: https://github.com/denschu/rcswitch-rest
- GUI: https://github.com/denschu/home.pi
- Switch Controller: https://github.com/denschu/rcswitch-pi
PS: My friend Daniel laughed about the selected version number “1.0”. Yes, it’s “1.0.”! It’s already in production! 😀
More articles
fromDennis Schulte
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Dennis Schulte
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.