HTML5 Inside – Geolocation

August 14th, 2010 by pyrat

Gps in orienteering
GPS tracking used in World Champs Orienteering

In this series I am going to write about the new whizz bang things which fall under the HTML5 umbrella. I am going to attempt to find out whether it is ‘hype or hardcore’.

Geolocation

Geolocation is the art of finding out where a user is. This can be as rough as country, or as fine grained as an exact latitude / longitude coordinate set.

Traditionally geolocation in the browser consisted of querying the user’s IP again a database. Usually this allowed you to find out what city a user was in. Nowadays, there is a geolocation API which is targetted specifically toward Mobile devices.

The W3C has an api for geolocation which is in draft stage at the time of writing.

Modern versions of Firefox, Chrome, Safari and Opera offer geolocation support. As far as I am aware all of these browsers actually implement the geolocation by querying a service provided by google. The google gears (deprecated) geolocation api has been natively implemented by the major browsers.

How does the actual geolocation work?

Note: The API Described is the old gears API but as HTML Geolocation currently uses this it should be seen to be relatively similar.

An HTTP POST is made containing JSON data which looks like the following.

  {
    "version": "1.1.0",
    "host": "maps.google.com",
    "home_mobile_country_code": 310,
    "home_mobile_network_code": 410,
    "radio_type": "gsm",
    "carrier": "Vodafone",
    "request_address": true,
    "address_language": "en_GB",
    "location": {
      "latitude": 51.0,
      "longitude": -0.1
    },
    "cell_towers": [
      {
        "cell_id": "42",
        "location_area_code": 415,
        "mobile_country_code": 310,
        "mobile_network_code": 410,
        "age": 0,
        "signal_strength": -60,
        "timing_advance": 5555
      },
      {
        "cell_id": "88",
        "location_area_code": 415,
        "mobile_country_code": 310,
        "mobile_network_code": 580,
        "age": 0,
        "signal_strength": -70,
        "timing_advance": 7777
      }
    ],
    "wifi_towers": [
      {
        "mac_address": "01-23-45-67-89-ab",
        "signal_strength": 8,
        "age": 0
      },
      {
        "mac_address": "01-23-45-67-89-ac",
        "signal_strength": 4,
        "age": 0
      }
    ]
  }

It has been designed to work with both mobile and wifi_enabled devices. The browser implementations map to native APIs on the device. So either a simple Lat/Lng is submitted potentially obtained from GPS (easy for google) or wifi_tower mac_addresses, or cell_tower information. Google can use this information to try to geocode a location.

The response is also in JSON. We love JSON here at simplyexcited, XML is dirty.

  {
    "location": {
      "latitude": 51.0,
      "longitude": -0.1,
      "altitude": 30.1,
      "accuracy": 1200.1,
      "altitude_accuracy": 10.1,
      "address": {
        "street_number": "100",
        "street": "Amphibian Walkway",
        "postal_code": "94043",
        "city": "Mountain View",
        "county": "Mountain View County",
        "region": "California",
        "country": "United States of America",
        "country_code": "US"
      }
    }
  }

The old json api is readable on this wiki page

Why this is good.

The geolocation api allows you to build location aware web applications which have access to native location apis. Bringing native hardware to web applications makes the future bright and takes us to a more webby non-native future.

How do I use it then?

Google maps V3 API has a great example of geocoding to put your location on a map.

  <!DOCTYPE html>
  <html>
  <head>
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
  <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
  <title>Google Maps JavaScript API v3 Example: Map Geolocation</title>
  <link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
  <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
  <script type="text/javascript" src="http://code.google.com/apis/gears/gears_init.js"></script>
  <script type="text/javascript">
 
  var initialLocation;
  var siberia = new google.maps.LatLng(60, 105);
  var newyork = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
  var browserSupportFlag =  new Boolean();
  var map;
  var infowindow = new google.maps.InfoWindow();
 
  function initialize() {
    var myOptions = {
      zoom: 6,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
 
    // Try W3C Geolocation method (Preferred)
    if(navigator.geolocation) {
      browserSupportFlag = true;
      navigator.geolocation.getCurrentPosition(function(position) {
        initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
        contentString = "Location found using W3C standard";
        map.setCenter(initialLocation);
        infowindow.setContent(contentString);
        infowindow.setPosition(initialLocation);
        infowindow.open(map);
      }, function() {
        handleNoGeolocation(browserSupportFlag);
      });
    } else if (google.gears) {
      // Try Google Gears Geolocation
      browserSupportFlag = true;
      var geo = google.gears.factory.create('beta.geolocation');
      geo.getCurrentPosition(function(position) {
        initialLocation = new google.maps.LatLng(position.latitude,position.longitude);
        contentString = "Location found using Google Gears";
        map.setCenter(initialLocation);
        infowindow.setContent(contentString);
        infowindow.setPosition(initialLocation);
        infowindow.open(map);
      }, function() {
        handleNoGeolocation(browserSupportFlag);
      });
    } else {
      // Browser doesn't support Geolocation
      browserSupportFlag = false;
      handleNoGeolocation(browserSupportFlag);
    }
  }
 
  function handleNoGeolocation(errorFlag) {
    if (errorFlag == true) {
      initialLocation = newyork;
      contentString = "Error: The Geolocation service failed.";
    } else {
      initialLocation = siberia;
      contentString = "Error: Your browser doesn't support geolocation. Are you in Siberia?";
    }
    map.setCenter(initialLocation);
    infowindow.setContent(contentString);
    infowindow.setPosition(initialLocation);
    infowindow.open(map);
  }
  </script>
  </head>
  <body onload="initialize()">
    <div id="map_canvas"></div>
 
  </body>
  </html>

View the working example

Simplest working example

Stick this in your firebug console and run it.

  if(navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      alert("Your lat/lng pair is" + position.coords.latitude + ", " + position.coords.longitude);
    }
  } else {
    alert("Your browser does not support W3C geolocation.");
  }

Conclusion

So.. Geolocation. Hype or Hardcore? I think hardcore.

Sencha / ExtJS Rant

July 29th, 2010 by pyrat

Rant

Decided to start ranting about things as I become more of a grumpy old man!
I am not an expert in extjs but have a working competance.

  • It is really slow to develop with.
  • Memorizing apis and setting keys on objects is dull and leads to messy code.
  • The templating system is dirty.
  • HTML in javascript is bad.
  • Not SEO friendly.
  • CSS is clumsy and ugly, just like the rendered html. (You essentially have an empty html document which ExtJs writes to.)
  • When you get an error or problem it is common to see the ‘white screen of death’ with accompanying cryptic error messages.
  • Testing seems non existant and its really just a method of apple-r / ctrl-f5 and pray.

Mobile Web Development

  • Mobile web development is mainly using the advanced nature of webkit CSS3, built-in hardware accelerated animations and using touch events rather than click events.
  • Design for the mobile web is a knowledge of what webkit gives you and the ability to work with small screens effectively.
  • Mimicking native applications is not the way forward. Look at gmail for iphone as an example of how good custom approaches can be.
  • Writing web applications for the mobile web should harness the advantages of a web based approach, not shoehorn a native approach into a monolithic javascript object.

These advantages include:

  • Writing HTML and CSS by hand. (lets get semantic man!)
  • Unobtrusive javascript. – Javascript is great, unobtrusive javascript is amazing.
  • Generating HTML with your favourite web framework (rails, django, symphony). This is powerful but also you need to think about html manifests and caching to not affect performance on shaky connections. If you shift paradigm and think of the web framework as an html generator / ajax interface this helps. (helped me)
  • Knowledge of the fancy new functionality that webkit browsers provide is the main new skill required.
  • Keeping a lot of your business logic in a web framework allows for easy testing using mature tools.

Canoeing in the Stockholm Archipelago

July 9th, 2010 by pyrat

Canoeing in the Stockholm Archipelago
Canoeing in the Stockholm Archipelago

The plan was to take a trip to the Stockholm archipelago and experience ‘endless islands’ in the most simple form of sea transport.
The sea kayak. We wanted to go as wild as possible so made the decision to try and get kayaks from as far out as possible in the archipelago
so that we were in the wilderness as quickly as possible.

I had only been in a sea kayak once before going on the trip, but had done a wee bit of freshwater kayaking. This proved to be enough, but I was glad
that I had been taught some paddling technique from former world adventure race champion Chris Forne.

Other preparation was to get a few drybags together and to test out some kit which we plan to use on a slightly bigger expedition later in the
summer.

Day 1

I woke up in a large ferryboat approaching Stockholm having been in Helsinki the night before. The last thing I could remember was
doing klinsmans over a bunch of swedes laid out in the corridor. Too much high quality russian vodka had been consumed!

After arriving in Stockholm, priority was to stock up on food. We bought food for the whole trip in one go. There is a wee bit of thinking required to
do this, but its much better having all the food sorted in a oner. Cost about £60 for all the food.

A bus, then a slow ferry took us to the town of Berg on the Island of Moja. From here, it was time to sort out all our stuff and leave the beer soaked
jeans and smelly orienteering shoes behind!

Getting our sh*t together
Getting our shit together

After getting maps from the kayak guy, fixing a broken rudder and getting everything packed, we were on our way. We paddled for about 2.5 hours through beautiful thin waterways in the evening sunshine.

We randomly picked a little island that looked like a good starting point for the next day and went about getting out of the boat. Turned out there is a lot of bare rock in the archipelago which has a slimy covering. This means you have to pick out inlets and grassy areas for landing the kayak. We found this out the hard way. First, I got out of the boat and proceeded to fall over and swim in the deep water. Next, I held onto the boat and ‘helped’ Helen get out of the water. The result was she went swimming too!

Sunset with the Kayak
Sunset with the Kayak

We setup campsite and for the first time felt the sense of peace and chilledness that was to set the tone for the next few days.

Tree Banter
Tree Banter

Day 2

The plan for day 2 was to do an 8km open water stretch to reach the Store Nåsa nature reserve. A collection of wild islands in the outer archipelago.

Wilderness
Wilderness

For some reason I was crapping it, the idea of falling out of the kayak in open sea seemed daunting. Luckily nothing with awry and we made it to the islands in the mid afternoon. We setup camp then I tried some fishing with the rudimentary fishing equipment I had taken along. I was unsuccessful but luckily we had enough food to get by.

Jarlsberg and Wine
Jarlsberg and Wine

Day 3

Bantered about the outer islands looking at the protected birdlife and lazing around in the sunshine. We went swimming in the afternoon sun and got attacked by a couple of arctic tern birds.

Arctic Tern
Arctic Tern

The wind dropped so we decided to make the open water paddle back to the moja reserve. Quick dinner and wine, then hardcore paddling. Open water navigation is difficult, you really need to trust your compass and not your eyes!

We found another top class little island, with a top view and no mosquitos. Best of the trip.

Sweet campsite
Sweet campsite

Day 4

As we had been carrying all our drinking water (cooking with sea water however) we were running a little low so decided to try and take a detour via a well to get some more water.

Cooking equipment
Cooking equipment

We hunted for a bit, then had lunch, then tried again and managed to find it! Cold fresh water on a hot sunny day was ideal.

Well
Well

A couple of hours paddling and later we started looking for an island to setup camp. The first one I was attacked by another arctic tern, then at the second one I disturbed a family of toads sheltering in a drying up bog.

We managed to find another camp spot which was pretty sweet.

Sweet Campsite
Sweet Campsite

Day 5

This was the last day of the trip, we left relatively early for us (9:30am) and proceeded back towards berg to return the kayak.

We stopped at a wee town for some lunch then made the paddle back to Berg. On the way we nearly hit a ferry head on and the result was the we had to ride the wake! We hit is straight on a were happy we had spray decks!

When we arrived back in Berg it was midsummer, a big party in Sweden; especially big in moja. There were loads of fast speedboats with noisy engines. I have decided that if I had the pleasure of being able to decide between getting a yaught, or getting a speedboat, I would go for a speedboat any day! Those things are PHAT.

Ended up in 747 that night. (converted into a hostel at Stockhol Arlanda Airport)


Jumbo Hostel

Doing it yourself

Can fully recommend this trip, it was pretty relaxed with not a great deal of physical effort. You could have gone more full on and did bigger kayaking distances than us if you like.

Hired the kayaks from Möja Havskajaker

  • Remember you need all your water so make sure you have enough vessels. 2l per person per day is enough.
  • Buy all your food before starting the trip. There is a supermarket in Berg but recommend just buying all of the stuff you need in Stockholm as there is more choice in the supermarkets there.
  • You can get petrol in the islands so a liquid fuel stove works quite well.
  • Watch out for mosquitos as there were quite a few at night so you need a mossie proof tent and the ability to choose good campspots.

Walking into the sunset
Walking into the sunset

Node.js Brief Overview

July 5th, 2010 by pyrat

I managed to get the time to do some research into Node.js last week. I have been meaning to check out the new coolness for hipster nerds like myself. I will try to explain some of the node concepts as I understand them.

Event based

Concepts borrowed from ruby’s event machine, python’s twisted and the event based closure syntax of javascript.

Often the plan when it comes to scaling request serving in web apps is to use threads. However there is an alternative method which yields better results. This is the single thread event loop and a good example of event based vs threading is that of a load test between apache and nginx.

Apache the worlds most popular webserver. Nginx is a wee russian webserver which punches beyond its weight.


Nginx versus Apache (with the worker-MPM) for serving a small static file.


Because Nginx is event-based it doesn’t need to spawn new processes or threads for each request, so its memory usage is very low.

These graphs are borrowed from this excellent post on the subject

Its all about the IO man

RAM is fast. Disk, DB and Network are very slow in comparison. This results in programs spending a lot of time waiting for IO operations to complete. Node approaches this as being completely the wrong way of doing things and everything should be non-blocking.

The problem being that most IO libraries are blocking, so there is a movement to upgrade these libraries to be non-blocking but there is also a c based thread pool which node uses to achieve non-blocking whilst using blocking IO Drivers.

Event based is hard

Coming from an OOP MVC background is a hard approach direction to Event based programming. A better approach is looking at javascript in the browser and a working relationship with a framework such as jquery which shows how events can be used in the javascript world to achieve unobstrusive RIA functionality to your web application.

Do I really want to build a website with this?

Currently it seems strange to me that you would want to build a website with server-side javascript. There are a lot of great frameworks out there for building web applications and most of them are a lot more mature and powerful than the javascript offerings.

However, I think that the power of node is in the access to low level functionality to build your own low level network applications.

Previously, these areas have been limited to people with black art C skills in memory management and other old school tools. Now, any joe blow with some javascript skills and create something which does some powerful things with good performance.

So essentially, programmers who have grown up in the internet age can now write ace applications in a way which was previously not possible. In my view, this is the main merit of node.

Simple Proxy in Node

To achieve an http proxy you would typically install something like squid which has a lot of configuration options

Obviously squid is very powerful and bursting full of features that you need, you should probably use it actually. However it is really easy to write a proxy in node.

  var http = require('http');
  var sys  = require('sys');
 
 
 
  function server_callback (request, response) {
    var proxy = http.createClient(80, request.headers['host']);
    var proxy_request = proxy.request(request.method, request.url, request.headers);
 
    proxy_request.addListener('response', function (proxy_response) {
      proxy_response.addListener('data', function(chunk) {
        response.write(chunk, 'binary');
      });
      proxy_response.addListener('end', function() {
        response.end();
      });
      response.writeHead(proxy_response.statusCode, proxy_response.headers);
    });
    request.addListener('data', function(chunk) {
      proxy_request.write(chunk, 'binary');
    });
    request.addListener('end', function() {
      proxy_request.end();
    });
  }
 
 
  http.createServer(server_callback).listen(8080);
  sys.puts("Server running on port 8080");

There is a proxy which a little bit more functionality which is available node proxy

How can I have a go?

The easiest installation path I have seen is to install homebrew then

sudo brew install node

You can then launch the proxy example with:

node proxy.js

I want to put it LIVE

Best plan is to deploy it with nginx as a frontend which proxies request to the node instance. One option is using it with upstart and monit.

This blog post describes the process really well. Heroku are in the process of starting of offer node support; but this is still in a closed beta.

Conclusion

I hope this has given a brief overview of node and it helps you to decide whether to have a go or not.

Wicked Wednesday – Bon Voyage

June 30th, 2010 by pyrat

This is one of the best snowboard video teasers I have seen for a while.

BON VOYAGE TEASER from VIDEOGRASS on Vimeo.

Google Storage Interoperability With Amazon S3

June 27th, 2010 by pyrat


A google server

Google storage was recently released as an open beta for developers to work with. All in all it seems like an Amazon S3 clone and whilst they have their REST api for integration they also support the Amazon S3 api.

Originally I was planning on writing a ruby wrapper of this api but decided to see if I could modify with existing aws-s3 gem to work with google storage.

After some in depth reading of both apis and understanding of the aws-s3 gem I have modified it to also work with google storage.

My github fork contains these modifications.

To use:

 
  require 'aws/s3'
  include AWS::S3
 
  Base.establish_connection!(
      :access_key_id     => 'abc',
      :secret_access_key => '123',
      :default_host => "commondatastorage.googleapis.com"
    )

Note the addition of the default_host to connect to google instead of AWS.

From then on you can use the gem as normal as is described in the Readme.

Lightweight SVN diff wrapper opendiff

June 3rd, 2010 by pyrat

I have been using SVN a bit recently (euch after the power of git) and have been doing some merges using
FileMerge (opendiff) a utility which comes with the mac developer tools.

To make this play with SVN 1.5 or greater you have to use a wrapper to call the tool. There is an existing toolset written in shell script but they do not seem to work for me (1.6.9).

  #!/usr/bin/env ruby
 
  # A ruby wrapper
 
  unless ARGV.length == 5
    puts "Incorrect number of arguments"
    exit
  end
 
  left = ARGV[3]
  right = ARGV[4]
 
  `opendiff #{left} #{right} -merge #{right}`
  exit(0)

Slap this script somewhere and make it executable. Edit your .bash_profile to include the following:

  export SVN_MERGE='/path/to/svn_diff_wrapper.rb'

So when you get presented with the merge options press l and it should load filemerge for merging power.

Wicked Wednesday – Chrome Speed Tests

May 26th, 2010 by pyrat

In case you havent seen this already. Original promotional video for google’s web browser.

Super Sunday – Go Pro Camera Self Filming

May 16th, 2010 by pyrat

Check out this excellent self filming series of park runs!

Courtesy of whitelines

Wee CSS Tidy Textmate Bundle

May 12th, 2010 by pyrat

Clutter
Nobody likes clutter!

I am getting used to pretty code. I have the ruby beautifier textmate bundle, the excellent jstools (a beautifier and jslint validation for javascript) and my home made wee php beautifier for my php code.

One thing that was missing was my css code, large css files can quickly get out of hand and especially when working with other developers it is nice to be able to make code look nice and clean with the minimal amount of effort.

This also fits in with the no broken window theory analogy coined by the pragmatic programmers

Andy Hunt said:

Researchers studying urban decay wanted to find out why some neighbourhoods escape the ravages of the inner city, and others right next door—with the same demographics and economic makeup—would become a hell hole where the cops were scared to go in. They wanted to figure out what made the difference.

The researchers did a test. They took a nice car, like a Jaguar, and parked it in the South Bronx in New York. They retreated back to a duck blind, and watched to see what would happen. They left the car parked there for something like four days, and nothing happened. It wasn’t touched. So they went up and broke a little window on the side, and went back to the blind. In something like four hours, the car was turned upside down, torched, and stripped—the whole works.

They did more studies and developed a “Broken Window Theory.” A window gets broken at an apartment building, but no one fixes it. It’s left broken. Then something else gets broken. Maybe it’s an accident, maybe not, but it isn’t fixed either. Graffiti starts to appear. More and more damage accumulates. Very quickly you get an exponential ramp. The whole building decays. Tenants move out. Crime moves in. And you’ve lost the game. It’s all over.

We use the broken window theory as a metaphor for managing technical debt on a project.

The bundle is hosted on github. It uses the excellent CSStidy project behind the scenes so make sure that you have php installed on your machine as CLI. > version 5.

Ctrl + alt + option + c will beautify your css file that you have open in the browser. It assumes that you are using 2 spaces for a tab instead of tab characters. So make sure you are using soft tabs in your code.

Install Instructions

  • Download it
  • Double click on the tmbundle to install it.

Contributing

The source is available on github. One of the big things which can be added is the addition of textmate options to control the behaviour of CSSTidy. At the moment it just makes the CSS look pretty in a way that I think is pretty. It might be ugly to the one line per definition kids.