Over a million developers have joined DZone.

Dabbling in Home Automation

DZone 's Guide to

Dabbling in Home Automation

· DevOps Zone ·
Free Resource

A Swedish colleague of mine once told me that Clas Ohslon is termed a “husband kindergarten” by Swedish woman and I have to admit that if I’m ever nearby I do pop in because you never know when you might need a spare chainsaw chain, an extra flash drive or a spare part of your boat.

Anyhow during my latest jaunt I found that they’d started stocking home automation kit and were offering £10 off for every £50 spent. £100 (well £80) later I left with a variety of gadgets and not a clue what I was going to do with them.

For command and control I bought a Tellstick USB which was plugged into the NAS storage server (auto media archiving + uPNP / SMB for RaspBMC), for the ceiling lights I’d bought a bunch of NEXA LWNR 210′s which allow you to control the lights using the 300Mhz wireless comms or overriding with the existing switch, for sockets I used a combination of NEXA LMCR 1000′s and NEXA EYCR 2300′s (UK socket versions obviously).

After wiring up a good 50% of them I realised that I’d left the power on which I have to admit is a legacy of working on DataCenter power where uptime was more important than health and safety (ahh those were the days). Cue a quick trip to the Fuse box to prevent getting told off by the wife should I end up getting electrocuted.

Once everything was wired up and no fuses blown it was time to start automating!

As I was being lazy I opted to use the centralised “Telldus Live” product http://live.telldus.com/) rather than working out how to talk natively to the USB (although Telldus do support that) and quickly hacked together an Android widget (we use a Motorola Xoom with a dock as our XBMC / lighting / everything controller) and a PHP proxy to do the OAUTH comms with Telldus live;

The Android widget is very simple;

package net.networksaremadeofstring.zeus;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
public class ZeusTallLampWidget extends AppWidgetProvider 
  int N = 0;
	public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 
		N = appWidgetIds.length;
        for (int i=0; i<N; i++) 
            int appWidgetId = appWidgetIds[i];
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget2);
            views.setTextViewText(R.id.textView1, "Tall Lamp");
            Intent offIntent = new Intent(context, ZeusTallLampWidget.class);
            offIntent.putExtra("id", 197068);
            offIntent.putExtra("type", false);
            PendingIntent pendingOffIntent = PendingIntent.getBroadcast(context, 0, offIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            views.setOnClickPendingIntent(R.id.button1, pendingOffIntent);
            appWidgetManager.partiallyUpdateAppWidget(appWidgetId, views);
            Intent onIntent = new Intent(context, ZeusTallLampWidget.class);
            onIntent.putExtra("id", 197068);
            onIntent.putExtra("type", true);
            PendingIntent pendingOnIntent = PendingIntent.getBroadcast(context, 1, onIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            views.setOnClickPendingIntent(R.id.button2, pendingOnIntent);
            appWidgetManager.updateAppWidget(appWidgetId, views);
	public void onReceive(Context context, Intent intent) 
		super.onReceive(context, intent);
	    if (intent.getIntExtra("id", 0) != 0)
	    	API.switchSomething(intent.getIntExtra("id", 0),intent.getBooleanExtra("type", false));

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

<receiver android:name="net.networksaremadeofstring.zeus.ZeusHalogenWidget" android:label="Zeus Halogen Widget">
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
	<meta-data android:name="android.appwidget.provider" android:resource="@xml/widget" />

The switchsomething function is equally simple:

public static void switchSomething(final int ID, final boolean toggle)
		((Thread) new Thread()
			public void run()
					DefaultHttpClient client = new DefaultHttpClient(); 
					HttpParams params = new BasicHttpParams();
			        SchemeRegistry registry = new SchemeRegistry();
			        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
			        ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(params, registry);
			        DefaultHttpClient httpclient = new DefaultHttpClient(mgr, client.getParams());
			    	HttpGet request = null;
			    		request = new HttpGet("http://fictional.tld/telldus/on.php?deviceid=" + Integer.toString(ID));
			    		request = new HttpGet("http://fictional.tld/off.php?deviceid=" + Integer.toString(ID));
			        HttpResponse response = httpclient.execute(request);
			        String rawJSON = EntityUtils.toString(response.getEntity());
					JSONObject TagObject = new JSONObject(rawJSON);
				catch(Exception e)

Which in turn calls:

	require_once 'common.php';
	$DEVICEID = $_GET['deviceid'];
	$consumer = new HTTP_OAuth_Consumer(constant('PUBLIC_KEY'), constant('PRIVATE_KEY'), 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX');
	$params = array(
		'supportedMethods' => constant('TELLSTICK_TURNON') | constant('TELLSTICK_TURNOFF'),
		'id' => $DEVICEID,
		'response' => 'json'
	$response = $consumer->sendRequest(constant('REQUEST_URI').'/device/turnOn', $params, 'GET');
	echo $response->getBody();

Within 20 minutes I was turning ceiling lights, floor lamps and all manner of other gadgets on and off from my tablet!

The code is hacky and the OAUTH stuff really ought to be done natively in Android to save a step but I’m happy enough with it, with a single Android device I can search for and download some media to the NAS, queue it up on the RaspBMC to play over whichever TV in the house I want and then adjust the lighting in that room (or any room) to suit the mood and all using open source software.


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}