Endpoint

Projects and software by Matt Collinge @ www.mattcollinge.co.uk

Archive for the ‘Programming’ Category

Controlling Power Sockets using a Raspberry Pi

leave a comment »

The subwoofer we had in our home cinema setup died a few weeks ago, so I did my research and found a nice replacement. The only thing I didn’t spot was the fact it never goes into standby if there’s no signal (unlike the old one). I tried using some eco plugs which turn off peripherals when the TV was turned off.. but it learns the TV remote signals, and completely turns the TV off as well.. meaning that you have to hit the power button twice to turn the TV back on; that doesn’t work well with the Harmony all-in-one remote we use.

What I decided to do was buy an Energenie socket, which can be switched on/off wirelessly from a Raspberry Pi. The kit comes with 2 sockets and a transmitter to attach to the GPIO headers on the Pi, and costs about £20.

In my subwoofer scenario I basically want it switched on when the TV is on, and off when the TV is off. The TV has a Chromecast plugged into it which is visible on my local network. If you’ve got a Smart TV on your network, maybe that’ll be visible in the same way. So when the TV/Chromecast appear on the network, we know to switch on the power socket.

energeniesockets

Here’s the small Energenie transmitter attached to the GPIO headers on my B+.. it’s pretty tiny and the case I’ve got still fits over the top. Notice the small hole where you can attach an aerial.. if you want extra range, then you’ll need to solder one on.. I added a 135mm wire, since the range I got out of it just wasn’t enough to get from the dining room cupboard to the living room.

energeniepi

To put this together, we can use the Raspberry Pi Network Spy code I wrote in my previous blog posts on element14;

Raspberry Pi Network Spy – Part 1 – Initial Setup + d/b Schema
Raspberry Pi Network Spy – Part 2 – D/b Setup + PHP for the scanner

All we need is a new PHP page that’ll call one of the functions we’ve already written.. we need a list of the MAC addresses that are currently visible on the network, then check whether the Chromecast is there. Once we know whether the TV/Chromecast is on or off, we then call a Python script that will turn the Energenie socket on/off.

Here’s the PHP;

arp-chromecast.php

The Python script could follow the Energenie example script, but there’s actually an even more simple Python package which I’ve used in this project. To install it I did the following;

sudo apt-get install python-pip
sudo pip install energenie

Then I wrote this helper Python script (which we’ll call from PHP) that accepts a couple of parameters, like this callenergenie.py [on|off] [switch_number];

callenergenie.py

from energenie import switch_on, switch_off
import sys

if len(sys.argv)==1:
print ‘Please specify arguments like this callenergenie.py [on|off] [switch_number]’
print ‘eg. callenergenie.py on 1’
print ‘eg. callenergenie.py off 2′
else:
on_or_off = sys.argv[1]
which_switch = int(sys.argv[2])

if (on_or_off==’on’):
print ‘Switching on ‘, which_switch
switch_on(which_switch)

if (on_or_off==’off’):
print ‘Switching off ‘, which_switch
switch_off(which_switch)

Now that we’ve written the PHP & Python, all we need to do is run the PHP every minute to scan the network and do the switching. We’ll do this using another cron job;

crontab -e

*/1 * * * * sudo /usr/bin/php /var/www/arp-chromecast.php

Written by Matt

March 14, 2015 at 8:39 pm

Using Wireshark and MITM to explore a STB

leave a comment »

I’ve recently bought a new Freeview HD box from 3view. It has a whole host of features and can be considered a “connected” device. As with most high-end set-top-boxes (STB) it pulls software firmware updates from the web, and I was interested to see where it went to get these updates & how it knew they were available.

I know about using tools to sniff network traffic, but have only done this to sniff traffic coming directly out of the PC I’m running the capture software on. Buying this 3view box gave me more of an inventive to expand my knowledge & figure out how to capture the traffic from other devices.

It was actually relatively easy. I decided to do a Machine in the Middle (MITM) ‘attack’ which was documented over at the Wireshark wiki.

In my case I didn’t have 2 network cards, but did have a laptop with one network card, and a wireless card. In Windows XP I bridged the NIC to the Wireless adapter, then plugged in a cross-over cable that linked the 3view box to my laptop. Then, after a bit of messing about with IP addresses it started working.. my 3view box was accessing my wireless router via my laptop.

Now that all the traffic from the 3view box was going via my laptop, all I then needed to do was fire up Wireshark & take a look at the packets.

Intercepting the traffic allowed me to see where the box was going for it’s updates, and the User Agent. That’s been documented over at the 3viewer community website I set up for 3view owners.

http://3viewer.elementfx.com/

Written by Matt

September 11, 2010 at 1:49 pm

QR Code Bookmarklet

with 2 comments

QR Codes are a useful way of getting data to your mobile phone using it’s built-in camera. They’re basically 2D barcodes that can carry things like URLs and contact details. On Android I’d recommend using the app called Barcode Scanner to read QR Codes.

There were instances where I wanted to open up a webpage with a long URL on my phone & didn’t want to go through the hassle of copying and pasting it into one of those online QR Code generators.

This bookmarklet for Firefox and newer versions of IE lets you create a QR Code for the page you’re on.. it’ll default to the current page, but you can also override this with something else (like a URL from your clipboard, or whatever).

Add a new bookmark to your toolbar, and set the URL to the code below (I’d have put the proper link on here but WordPress disables the Javascript);

javascript:var%20sCode=prompt('Enter%20URL%20to%20encode',window.location);void(window.open('http://chart.apis.google.com/chart?cht=qr&chs=300x300&chl='+encodeURIComponent(sCode),'Qr%20code','top=100,left=200,width=350,height=350,status=yes'));

Written by Matt

January 29, 2010 at 7:44 am

iPhone and Android development with Titanium

leave a comment »

Over the past few months I’ve worked on a couple of mobile applications for the iPhone and Android platforms. I’d looked at Phonegap some time before that, but determined that it wasn’t up to the job, but more recently I stumbled across Titanium from Appcelerator. The idea is that you code up your apps using HTML and Javascript. The Javascript calls the Titanium API to create things like lists, dialog boxes, and phone features such as geolocation.

Some of the advantages of using Titanium are:

– No need to learn Objective-C (iPhone) or Java (Android)
– Leverage existing HTML + Javascript skills
– Write one version of the code that can be deployed to both platforms
– Code is compiled up into native applications which are accepted in the App Store
– Potential to deploy to other platforms in the future (e.g. Blackberry, Symbian)

The level of support provided by the Appcelerator staff on the official forums is brilliant, and the tutorial videos are good for those who want to get an overview of creating apps without wading through documentation.

You’ll still need a Mac if you want to develop for the iPhone, because Titanium makes use of the iPhone SDK. But if you just want to do Android development then you can use Window or Linux as well.

Although you’ll be developing 1 set of code for both the iPhone and Android, you’ll probably want to customise the UI slightly differently for each platform. For example, Android apps often hide away items such as ‘Settings’ and ‘Help’ under the Menu button. It’s simple to code this kind of thing up:

	if (Titanium.Platform.name == 'android') {
		var menu = Titanium.UI.createMenu();
		menu.addItem("Help/About", function() {
			displayWindow('Help / About', 'window_about.html');
		}, Titanium.UI.Android.SystemIcon.HELP);
		Titanium.UI.setMenu(menu);
	} else {
		data.push({title:'Help / About',image:'tabicon_help.png', color:'#ffffff'});
	}

That code will create the Help/About option under a menu on Android, and add it to the home screen’s list on the iPhone. Simple.

Titanium is an awesome framework so if you’re considering developing for the iPhone and/or Android then I’d highly recommend you take a look.

Written by Matt

January 13, 2010 at 7:10 am

Power Meter Plus in PC Pro Magazine

leave a comment »

pc-pro-logo Power Meter Plus has been getting a lot of coverage this month; it’s been mentioned on dozens of blogs and now in PC Pro magazine issue 172, in fact I think Lifehacker might have picked up on it from there & the blogs picked up on Lifehacker’s article.

pcpro-jan-2009

Written by Matt

January 5, 2009 at 7:30 am

Power Meter Plus featured on Lifehacker

leave a comment »

Lifehacker is one of my daily visits, so it was brilliant to see that it had Power Meter Plus as the Featured Windows Download :-D

Written by Matt

December 31, 2008 at 3:49 pm

Creating a Netvibes / iGoogle Gadget for Multi-Image Display

leave a comment »

To help make it as easy as possible for family members to see new pictures from the Collinge household I decided to set them up with Netvibes homepages, each containing a widget to display the latest photos from Picasa Web Albums. Picasa Web Albums provide an RSS feed that you can subscribe to which is a good start.. but I couldn’t find a way to display them just as I wanted.

The spec is to display the latest images, over as many columns as the user specifies.. and have the images resize to fit the width of the widget. They pretty much get displayed in a grid style layout.

Step 1) Get the URL for Picasa Web Albums (or whatever service you’re using) and make sure it works. The first gotcha here was that Picasa Web Albums has a limitation which means that images > 800px will not be embedded. They’ll result in a 404 File Not Found. To get around this, append ?imgmax=800 to the RSS’s URL.

Step 2) The feed for Picasa Web Albums is sorted in ascending date order.. I wanted it in descending date order so that the latest photos show first. To do this I chose to re-format the feed using Yahoo Pipes.. it’s a way of tinkering with a feed an invaluable for times when you need to do something simple like this.

Picasa gives you an Atom-based feed which seems to be causing a few issues with my code.. it basically makes the images go into a different node from the one I expected.. and I’ve been unable to work out exactly where it’s putting them. The best way around this is to simply run the RSS feed through a simple Yahoo Pipe; I’ve published one which sorts the images in date descending order. Use that and copy the RSS feed it generates.

Step 3) Create a new widget using UWA so that it works with Netvibes and iGoogle. This is relatively simple.. just requiring a bit of coding to make it happen. As usual I’ve tried to make the code as generic as possible & driven by user preferences. The user can specify which node in the JSON object (returned from the RSS feed) contains the image to display.. useful when dealing with non-standard image enclosures. It will default to the first enclosure at item.enclosures[0].url

The finished widget is published here.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:widget="http://www.netvibes.com/ns/"  >
	<head>
		<title>Multi-Image Display</title>
		
		<meta name="author" content="Matt Collinge" />
		<meta name="email" content="do-not-email@mt2009.com" />
		<meta name="description" content="Display multiple images from an RSS feed. Useful for feeds like those from Picasa Web Albums" />
		<meta name="version" content="1.0" />
		<meta name="website" content="http://eco.netvibes.com/widgets/298784/multi-image-display" />

		<meta name="keywords" content="image, rss, picasa, web album, picture, multiple, display, grid" />
		<meta name="autoRefresh" content="15" />
		<meta name="apiVersion" content="1.2" />
		
		<link rel="stylesheet" type="text/css" href="http://www.netvibes.com/themes/uwa/style.css" />
		<script type="text/javascript" src="http://www.netvibes.com/js/UWA/load.js.php?env=Standalone"></script>
		
		<style type="text/css">
			.imageDisplay {
				margin:0;
				padding:0;
			}
		</style>
		
		<widget:preferences>
			<preference name="title" type="text" label="Title" defaultValue="Multi-Image Display" />

			<preference name="url" type="text" label="RSS Feed" defaultValue="" />
			<preference name="limit" type="range" label="Number of images to display" defaultValue="10" step="1" min="1" max="50" />
			<preference name="columns" type="range" label="Number of columns to use" defaultValue="2" step="1" min="1" max="8" />
			<preference name="imagenode" type="text" label="Node in RSS Feed Containing Image" defaultValue="item.enclosures[0].url" />
		</widget:preferences>
	
		<script>
			var BasicRSSReader = {};
			 
			BasicRSSReader.feed = false;
			 
			widget.onLoad = function() {
				if (widget.getValue('url') === '' || widget.getValue('url') == undefined) {
					widget.setBody('Please edit the preferences and enter the URL of the RSS feed where you want to take images from.<br><br>. Use a feed re-formatter like Yahoo Pipes if you need to tinker with a 3rd party RSS feed.');
				} else {
					widget.body.addClassName('imageDisplay');
					widget.setTitle(widget.getValue('title'));
					UWA.Data.getFeed(widget.getValue('url'), BasicRSSReader.display);
				}
			}
			
			BasicRSSReader.display = function(feed) {
				var bodyHTML = '';
				if (feed) BasicRSSReader.feed = feed;
				
				var imageWidth = widget.body.getDimensions().width / widget.getValue('columns');
				var imageCount = 0;
				var columnCount = 0;
				
				bodyHTML += '<table border=0 cellpadding=0 cellspacing=0>';
				for(var i=0; i < BasicRSSReader.feed.items.length; i++) {
					var item = BasicRSSReader.feed.items[i];
					
					if (imageCount >= widget.getValue('limit')) {
						bodyHTML += '</tr>';
						break;
					}
					
					if (columnCount == 0) {
						bodyHTML += '<tr>';
					}
					bodyHTML += '<td><a href="' + item.link + '"><img src="' + eval(widget.getValue('imagenode')) + '" width="' + imageWidth + '" /></a></td>';
					
					columnCount++;
					
					if (columnCount == widget.getValue('columns')) {
						columnCount = 0;
						bodyHTML += '</tr>';
					}
					
					imageCount++;
				}
				bodyHTML += '</table>';
				
				if (imageCount==0) bodyHTML = 'Unable to load feed.';
				widget.setBody(bodyHTML);
			}
		</script>			
	
	</head>
	<body>
		<p>Loading...</p>

	</body>
</html>

Written by Matt

December 31, 2008 at 11:15 am

Follow

Get every new post delivered to your Inbox.