Chromecast setup

Chromecasts are £40-odd quid on Amazon.co.uk, and we’re interested in using them at work, so I got one to look at. Here are the bits you get in the box:

Chromecast pieces form the box

And here’s a walk through of the setup using Mac OS X (10.8.4) and a Samsung 6000-series TV.

Overall – the setup was a bit longer and more involved then I’d anticipated, and it’s not really clear what’s going on, unless like me you’re working with a device that does more or less the same thing. The setup worked almost perfectly though and the result is impressive.

The way the setup works is that the device broadcasts a wifi network, you connect to it after some visual checking (it does the connecting automatically via an app), and then you tell it your wifi connection details – the app gathers the names of wifi networks but you tell it the password. We are doing the same thing in a manual way in Radiodan and the Arduino Yún does something similar. My colleague reports that it is smoother on an Android app, and I guess Apple laptops probably are not the key target devices, since the functionality is like Airplay.

You need to install an app for the setup and an extension in Chrome to ‘cast’ things; for YouTube and a few other sites you cast directly in the page, which as I understand it, makes the Chromecast device make a separate call to the site for the best version of the video. For other things you just get the whole browser tab, including fullscreen if you like. The Chromecast extension can

  • access your data on all websites
  • access your tabs and browsing activity
  • manage network connections

Not sure what those mean precisely yet.

You don’t have to be logged into Google to set it up or use it, and I wasn’t.

Here are the instructions:

Chromecast box - instructions

You put the chromecast into the HDMI socket and plug it into the mains via a mini USB. Flip through sources on the TV and find the screen that looks like this:

Chromecast set me up screen on the TV

At this point we spotted a new wifi network, ‘Chromecast4827′.

On the computer (Mac OS X) you go to the Chromecast setup link and download and install an app:

Mac OS X screenshot of Chromecast installation app

When you run it it asks you to say which Chromecast you are installing – I forgot to take a screenshot of that bit.

Then the app is obviously connecting to the wifi network. The twee ‘Back in a snap’ makes me want to lightly punch someone, but that’s all part of the current infestation of corporate cutesiness, so I guess I have to live with it.

Screenshot of app connecting the Chromecast to the wifi network

I didn’t have to change the input, this code just appeared…

Screenshot of app showing the code

…on the TV:

The code on the TV

Then you wait a while for it to download software and restart.

Chromecast on the TV downloading updatesScreenshot of app explaining that the Chromecast is downloading updates

TV says ‘ready to cast’:

TV says ready to cast

‘Continue’ on the app, then we get ‘start using chromecast’:

App success screen

‘Start using Chromecast’ takes you to a link in Chrome.

‘Hang in there’ *light punch*

Link to extension in Chrome

Google Cast extension wants to know your brain:

Google Cast extension permissions requested

Once the extension was installed, I watched the ‘how to’ video locally –

Chromecast how-to video

- then tried to play it remotely – it didn’t work.

A different YouTube video worked, though it grumbled when I pressed the extensions ‘cast’ button and prefered me to use the one in the YouTube page:

YouTube video - suggesting use of the in-page buttonYouTube video working on the TV

The nice thing about doing it like this is you can open a new tab locally and it carries on playing.

iPlayer worked by casting using the extension – in full screen it looked pretty good:

iPlayer on Chromecast

- although in full screen you can’t open another tab.

Two little annoyances

Since it was raining this afternoon, I did a couple of things that have been bugging me for a while. Here are some quick notes.

GiffGaff ‘adult’ filter

GiffGaff is a really great pay-as-you go mobile provider for people like me who use a lot of data (the £12 per month option gives you unlimited data and I can use the minutes for confcalls). However, it runs on the O2 network who use a blacklist for ‘adult’ content. Mostly when I hit a blocked page it is a random blog I have arrived at via Twitter, and it is not clear why it is ‘adult’. I don’t know where these lists come from, nor how sites end up on one. As this powerful survivor post and this ORG post on the Cameron firewall illustrate, it is far from obvious how to make the distinction between the kinds of sites that might help people who are victims trying to find out more, and the kinds of site that kids shouldn’t be looking at.

I loathe this conflation of ‘aimed at over 18s’ and ‘porn’, and these are difficult issues. But ok, I am an adult. If you go to GiffGaff’s ‘remove adult filter’ in the UK you get the option to

A). Add two lines from your machine-readable passport (the ones with all the <<<<s in them) OR
B). Add in your gender and drivers' license number

I don't drive (and I don't see what my gender has to do with anything – anyway, can't you drive when you're 17?). So, passport then. The two lines include my: name, gender, date of birth, passport number, passport expiry date (and four checksums).

I really object to this. I'm pretty careful with my data and I don't expect to have to give out a surfeit of personal information to a site just to look at a blogpost when I'm on the move. I was getting angry about this on Twitter and someone (I forget who sorry) suggested that I could use this algorithm to generate the appropriate string. And it works: I made one change to my passport number to test it. The code is here. Make sure you get the length of the first string right – the error reporting is ambiguous. Given that it is a publicly available algorithm it maybe wasn’t the best way for them to get people to prove their age.

Getting back Nike Fuelband data

I love my fuelband and have successfully gamified myself into doing much more moving about than I used to do because of it. The Fuelband is a robust, water-resistant accelerometer worn on your wrist. You set an activity goal in terms of Nike Fuel ‘points’ (whatever they are), but it also tracks steps and has a nice watch and lots of colourful LEDs light up when you reach your goal.

It is a USB device, and when you plug it in it phones home, firing up an app on your laptop and sending your data to the Nike cloud where you are supposed to compare progress with others and get badges for progress and other nonsense. Actually I find that I use it as a quick check of my activity levels throughout the day, and I don’t really look at my graphs, which in any case are not that interestingly implemented. I’ve been learning d3.js and I reckon I could make some nicer graphs, but there is no way to get an export of the data. Nike are planning a developer API but it is not available yet. Nevertheless, people have managed to get their data back, and I used this video to get mine. The short version:

  • you need the device id and an access token, which you can get using (for example) Burp, by setting it as the https proxy – (I had to click ‘forward’ to get it to work; I didn’t have to install the CA)
  • then you can make API calls like this:


curl -H "Content-Type: application/json" \
-H "appid: fuelband" \
-H "Accept: application/json" \
"https://api.nike.com/v1.0/me/activities/summary/260713?deviceid=XXX&access_token=XXX&endDate=270713&fidelity=96"

fin.

Extremely easy in fact.

I’d prefer for it not to send the data to Nike at all, but that will have to wait. There is more detail about the API calls available in the video.

(As a side-note, I suspect that these activity devices are not about selling hardware; a friend got Fitbit to send her a new one after she lost it, which is great customer service but suggests their business model might lie elsewhere).

Rotary Encoder for the Raspberry Pi

For some of the Radiodan applications Richard, Anton and I discussed on thursday at the Bristol Hackspace, we need a rotary encoder. For example, this ‘Wrong (W)radio: Time Travel Radio can play audio from the last few days, navigating time by turning the right hand knob:

Image

I’ve not done much work with the Raspi GPIO, but Richard found an Adafruit example, and then I found this one, that looked simpler on the face of it – except that my C isn’t exactly great, and doesn’t in fact exist. Anyway it had a nice simple example of how to wire a rotary encoder to the Raspi (plus an explanation of the other two legs on my rotary encoder – they’re for the built-in button).

After a bit of a struggle, I got it to work – the library needs wiringPi

git clone git://git.drogon.net/wiringPi
git pull origin
cd wiringPi
git pull origin
./build

then

git clone https://github.com/astine/rotaryencoder
cd rotaryencoder
nano test.c

contents of  test.c:

#include "stdio.h"
#include "rotaryencoder.h"
int main()
{
printf("Hello!\n");
wiringPiSetup () ;
/*using pins 23/24*/
struct encoder *encoder = setupencoder(4,5);
long value;
while (1)
 {
 updateEncoders();
 long l = encoder->value;
   if(l!=value)
   {
     printf("value: %d\n", (void *)l);
     value = l;
   }
 }
return(0);
}

Save and compile it:

gcc -lwiringPi program.c rotaryencoder.c -o test

Run it (GPIO stuff needs to be run as root): I was turning the rotary encoder anti-clockwise

sudo ./test
Hello!
value: -1
value: -2
value: -3
value: -4
value: -5
value: -6
value: -7
value: -8
value: -9
value: -10
value: -11
value: -12
value: -13
value: -14
value: -15

The wiring’s like this:

Image

Archers Avoider

Here are some rough notes from our IRFS hardware hackday so I can find them again. The hackday was organised by Cefn Hoile, Andrew Nicolaou and Jasmine Cox, and was utterly brilliant.

This is work by Dan Nuttall, Jasmine Cox, Sean O’Halpin, Nikolaos Tsipas and me (though I did little!) at a hackday organised as part of our 10% time at IRFS at BBC R&D.

The idea was to make a panic button for radio, that allowed you to skip all or part of a programme, e.g. the Archers.

aa_plan

here’s the version we made:

aa_green_box

here’s the more exciting ‘farmer’ interface, designed by Jasmine and hooked up by Nikolaos:

aa_farmer

Here’s a video of a wifi version I made at home: http://www.flickr.com/photos/nicecupoftea/8649416824/in/photostream/

It consists of a Raspberry PI, a home-made Shrimp with a button, some code that plays IP streams for the audio, which listens for changes to a file and switches streams when it sees a change. Code listens to the serial port and when it detects a button change, changes the right file. I guess we could use the GPIO on the Pi for the button, but I don’t know how to do that yet.

At home, I had a go with my own Pi – I had a power supply and wifi card for it, but no fancy display. This is what I used:

  • Raspberry pi
  • SD card (I used a speed 10 generic 8GB one)
  • some sort of speaker
  • wifi usb card for the pi
  • power supply for the pi
  • arduino or shrimp with a button

I installed wheezy on an SD card via this:

http://www.raspberrypi.org/downloads
http://elinux.org/RPi_Easy_SD_Card_Setup

I then put it in the PI, connected via ethernet and sharing internet on the Mac. I got the IP address using

ping 192.168.2.255

and looking in console.app for a response from a pi – it was 192.168.2.4. I ssh’ed to that using pi@192.168.2.4 password raspberry, then tried to update apt-get

sudo apt-get update
Err http://archive.raspberrypi.org wheezy InRelease

Err http://mirrordirector.raspbian.org wheezy InRelease

Err http://archive.raspberrypi.org wheezy Release.gpg
Temporary failure resolving 'archive.raspberrypi.org'

The default nameserver from the mac didn’t work. Using the google dns fixed it, though this kept getting overwritten on a reboot for some reason:

sudo nano /etc/resolv.conf

nameserver 8.8.8.8
nameserver 8.8.4.4

then update apt-get

sudo apt-get update

Install mpd player

sudo apt-get install mpd

[....] Starting Music Player Daemon: mpdlisten: bind to '[::1]:6600' failed: Failed to create socket: Address family not supported by protocol (continuing anyway, because binding to '127.0.0.1:6600' succeeded)
Failed to load database: Failed to open database file "/var/lib/mpd/tag_cache": No such file or directory
. ok

Install the stuff needed for Dan’s player code:

sudo aptitude install ruby1.9.1-dev #for bundler
sudo apt-get install libsqlite3-dev
sudo apt-get install git #install git

Install Dan’s code:

git clone https://github.com/pixelblend/radiodan.git # the code
sudo gem install bundler #to get all the required gems
cd radiodan
bundle install

Put the simple button code on the arduino using laptop:

// set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin

// variables will change:
int buttonState = 0; // variable for reading the pushbutton status

void setup() {
 // initialize the LED pin as an output:
 pinMode(ledPin, OUTPUT);
 // initialize the pushbutton pin as an input:
 pinMode(buttonPin, INPUT);
 Serial.begin(9600);
}

void loop(){
 // read the state of the pushbutton value:
 buttonState = digitalRead(buttonPin);
 //Serial.println(buttonState);
 // check if the pushbutton is pressed.
 // if it is, the buttonState is HIGH:
 if (buttonState == HIGH) {
  // turn LED on:
  digitalWrite(ledPin, HIGH);
  Serial.println("on");
 }
 else {
  // turn LED off:
  digitalWrite(ledPin, LOW);
  //Serial.println("off");

 }
}

Install required gem for Sean’s serial reading code:

sudo gem install serialport

add in Sean’s ruby code in radiodan/bin/read-serial.rb :

require 'serialport'

filename = ARGV[0] or abort "Need to specify path to file"
sp = SerialPort.new(filename, 9600)
sp.read_timeout = 100
sp.flow_control = SerialPort::NONE

p sp

TIMEOUT = 0.01
TIME_LIMIT = 0.25
PANIC_FILE = "../tmp/panic"

last_time = Time.now.to_f

state = :off

reading = true
begin
 while reading
  selectors = IO.select([sp], [], [], TIMEOUT)
  time = Time.now.to_f
  if selectors
   input = selectors.first.first
   data = input.gets.chomp
   state = state == :on ? :off : :on
   if state == :on
   File.open(PANIC_FILE, "wb") do |file|
    file.write Time.now.to_s
  end
 end
 p [data, state]
 flushing = true
 while flushing
  selectors = IO.select([sp], [], [], TIMEOUT)
   if selectors
    input = selectors.first.first
    junk = input.gets
   end
   time = Time.now.to_f
   if time > last_time + TIME_LIMIT
    flushing = false
   end
  end
 end
  last_time = Time.now.to_f
 end
ensure
 sp.close
end

plug in the arduino to the pi using the USB port, and identify it:

ls /dev | grep USB
> ttyUSB0

run the serial code in the background

cd bin
ruby read-serial.rb /dev/ttyUSB0

and

./bin/download # get the data - should run in the background
./bin/radio

-> at this point if it’s all running correctly it should work (hear R4 from speaker, press the button and it goes to radio 1 for 5 secs and then returns)

for wifi I used

http://dl.dropboxusercontent.com/u/80256631/install-rtl8188cus.txt

via

http://elinux.org/RaspberryPiBoardVerifiedPeripherals#USB_Wi-Fi_Adapters

I did this at the end, which took a looong time:

“Do you want to continue and update the software packages list, kernel software
packages and upgrade the Pi’s firmware and software or do you want to terminate
the script?”

get IP addresss with ifconfig and use wlan0

iwconfig

-> should be associated with an SSID

-> I had some problems with this…turning it off and on again worked :-)

Just for reference, here’s the full code for the exciting 7 segment LED display Cefn found for us that Jasmine wrote.

The old ebay listing is here and the library and sample code is here (zip file)


// set pin numbers:
const int buttonPin = 9; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
//We always have to include the library
#include "LedControl.h"
/* we always wait a bit between updates of the display */
unsigned long delaytime=250;
/*
Now we need a LedControl to work with.
***** These pin numbers will probably not work with your hardware *****
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD
We have only a single MAX72XX.
*/
LedControl lc=LedControl(12,11,10,1);

// variables will change:
int buttonState = 0; // variable for reading the pushbutton status

void setup() {

 lc.shutdown(0,false);
 /* Set the brightness to a medium values */
 lc.setIntensity(0,8);
 /* and clear the display */
 lc.clearDisplay(0);
 // initialize the LED pin as an output:
 pinMode(ledPin, OUTPUT);
 // initialize the pushbutton pin as an input:
 pinMode(buttonPin, INPUT);

 Serial.begin(9600);
  writeRadio4();
}

void loop(){

// read the state of the pushbutton value:
 buttonState = digitalRead(buttonPin);

 // check if the pushbutton is pressed.
 // if it is, the buttonState is HIGH:
 if (buttonState == HIGH) {
  // turn LED on:
  digitalWrite(ledPin, HIGH);
  Serial.println("on");
  writeRadio1();
 }
 else {
  // turn LED off:
  digitalWrite(ledPin, LOW);
  // Serial.println("off");
 }
}

void writeRadio4() {

 lc.setRow(0,7,0x05);
 delay(delaytime);
 lc.setChar(0,6,'a',false);
 delay(delaytime);
 lc.setChar(0,5,'d',false);
 delay(delaytime);
 lc.setRow(0,4,B00010000);
 delay(delaytime);
 lc.setRow(0,3,0x1D);
 delay(delaytime);
 lc.setDigit(0,1,4,true); // Display 3 to Digit 3, " "
 delay(2000);

 lc.clearDisplay(0);
 delay(delaytime);
}

void writeRadio1(){

 lc.setRow(0,7,0x05);
 delay(delaytime);
 lc.setChar(0,6,'a',false);
 delay(delaytime);
 lc.setChar(0,5,'d',false);
 delay(delaytime);
 lc.setRow(0,4,B00010000);
 delay(delaytime);
 lc.setRow(0,3,0x1D);
 delay(delaytime);
 lc.setDigit(0,1,1,true); // Display 3 to Digit 3, " "
 delay(delaytime);

 lc.clearDisplay(0);
 delay(5000);

}

SVG D3.js bar chart

This has been driving me up the wall. I haven’t felt so stupid in a long time. Anyway, since I managed it finally, here is some code:


<html>
<head>
<script type="text/javascript" src="d3/d3.v3.min.js"></script>

<style type="text/css">
.axis text {
font: 10px sans-serif;
}

.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="chart"></div>
</body>

<script type="text/javascript">
var margin = {top: 10, right: 10, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;

var x = d3.scale.linear()
.domain([0, 20])
.range([0, width]);

var y = d3.scale.linear()
.domain([0,100])
.range([height,0]);

var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");

var yAxis = d3.svg.axis()
.scale(y)
.orient("left");

var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);

svg.append("g")
.attr("class", "y axis")
.call(yAxis);

var data = [[1,100],[6,20],[20, 50]];

var bars = svg.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("x", function(d) {return x(d[0]) - 5;})
.attr("y", function(d) {return y(d[1]);})
.attr("width",10)
.attr("height", function(d) {return height - y(d[1]);})
.style("fill","blue");

</script>

</html>

and the output:

output

Adapted from this example on jsfiddle. Another good source of information is Scott Murray’s d3.js tutorials particularly scales and axes.