Building McLaren.com – Part 3: Reading Telemetry

I've just finished working on McLaren's new F1 site, http://mclaren.com/home, for the 2010 season, at Pirata London, for Work Club.

I'll be writing up what we've done here in several parts. Sign up for my RSS feed to keep updated.

Part three covers the JavaScript data for the telemetry panel, known as "The Race 1.0b".

Using JSON-P #

There's very little processing of the feed between the web server and McLaren. The telemetry data is simply reformatted for convenience and merged with the Commentary (which is actually added through a local source by a guy in the pit garage). We made sure we sent through as much data as we could get - though you may need a large screen to be able to see it!

Data is sent using JSON-P. This is so that the data can be acquired from the feed domain rather than the site domain; crucial since the data feed server is in a different network for performance.

JSON is a great way to mark up data for consumption by JavaScript. It's quick to assimilate, and very easy to read and debug. It's also far shorter in length than the equivalent XML structure.

One of the principles of the Nginx Http Push Module is request idempotency. If this doesn't mean anything to you, you're not alone. All this means is that the client should always request the same URL, but with different caching times set. This lets the caching mechanisms within nginx serve up all the messages posted since your last request. However, this is no use to us - there is simply no way to load json-p cross-domain without using script tags, and webkit-based browsers simply will not reload the scripts if the filenames are the same. (I suspect this is true of other browsers too actually, but I've got caching turned off for development in Firefox).

I append a randomised string to the end of my json-p requests (using cache:false in my jQuery ajax request) to avoid caching. The broadcast mechanism still works, but I'm unable to use the queue backlog in the nginx http push module. I have therefore set the maximum queue length to zero.

The disadvantage of this is that I will only receive packets of data that are sent when I am on the line as a subscriber. If my connection is patchy, then I might miss packets of data - not critical for telemetry, but a shame for any commentary that is sent through.

However, I am able to broadcast the JSON-P packets to vast numbers of subscribers.

JSON Format #

The 'standard' telemetry packet looks like this:

Dashboard.jsonCallback('{"drivers":{"HAM":{"code":"HAM","telemetry":{"timestamp":"18:43:38.078","nEngine":758,"NGear":0,"rThrottlePedal":0,"pBrakeF":2,"gLat":0,"gLong":0,"sLap":0,"vCar":0,"NGPSLatitude":-37.85131,"NGPSLongitude":144.97086},"additional":{"lap":"0","position":"6","is\_racing":"0"}},"BUT":{"code":"BUT","telemetry":{"timestamp":"18:43:38.317","nEngine":1695,"NGear":0,"rThrottlePedal":0,"pBrakeF":1,"gLat":0,"gLong":0,"sLap":0,"vCar":0,"NGPSLatitude":-37.84984,"NGPSLongitude":144.96927},"additional":{"lap":"0","position":"1","is\_racing":"0"}}}}');  

It's pretty clear what each term above means. The packet above is from a lap of the Australian Grand Prix in Melbourne.

The commentary, and all data in 'additional', is provided by the commentry team in the pits. This is why the lap and place can sometimes seem out of sequence.

At this point it's a good time to add a legal note:

Having said that, here are my thoughts on netiquette:

Ok, to continue. Every lap end, we get some extra information in the packet:

Dashboard.jsonCallback('{"drivers":{"HAM":{"lapTimeS":"91.959","maxSpeedKph":305,"meanSpeedKph":204,"maxLateralG":6,"code":"HAM","telemetry":{"timestamp":"17:47:32.693","nEngine":15877,"NGear":5,"rThrottlePedal":0,"pBrakeF":51,"gLat":1,"gLong":-2,"sLap":316,"vCar":202.6,"NGPSLatitude":-37.84817,"NGPSLongitude":144.96664},"additional":{"lap":"0","position":"7","is\_racing":"0"}},"BUT":{"code":"BUT","telemetry":{"timestamp":"17:47:32.938","nEngine":17276,"NGear":5,"rThrottlePedal":100,"pBrakeF":1,"gLat":0,"gLong":0,"sLap":593,"vCar":232.1,"NGPSLatitude":-37.846,"NGPSLongitude":144.96573},"additional":{"lap":"0","position":"2","is\_racing":"0"}}}}');  

Extra fields in this packet are:

How does it request the data? #

I use jQuery rather than Mootools. So, I rewrote Leo's Mootools plugin (provided for the chatroom on the pushmodule site) in jQuery. I'm not convinced it offers me anything much anymore, since I've taken out most of what it did, but it's easy to use. It's located at http://mclaren.com/_assets/js/site/jquery.nginx_subscribe.js .

I also use the jQuery JSON parsing plugin.

I then use those plugins with this code:

var Dashboard = function () {  
// URL of data feed  
var dashboardURL = 'http://feed.mclaren.com/feed/sub'; // Live service  
// on document load  
$(document).ready(function() {  
// create subscriber  
var dashboard\_subscribe = $.nginx\_subscribe(  
dashboardURL,  
function success(textResp) {  
// the script calls success function direct  
},  
function failure(resp) {  
if (window.console) {  
console.log('subscribe failure');  
}  
}  
);  
});  
var addCommentary = function(jsonStr) {  
alert(jsonObj);  
}  
var addTelemetry = function(jsonObj) {  
alert(jsonObj);  
}  
var jsonCallback = function(jsonStr) {  
try {  
var respJson = jQuery.evalJSON(jsonStr);  
if (respJson.commentary && respJson.commentary.length) addCommentary(respJson.commentary);  
if (respJson.drivers) addTelemetry(respJson.drivers);  
} catch (e) {  
if (window.console) {  
console.log(e);  
}  
}  
}  
return {jsonCallback:jsonCallback};  
}  

Obviously this script isn't great because it will either alert you several times a second if a race is on, or not respond at all. You'll need to set up an nginx feed server yourself (as described in Part 2), and start POSTing to it, before you see any responses out of race time, and you'll want to replace the alerts with something more useful.

I like to use the Net view of Firebug to watch the network traffic.

Cool uses of the data #

From the very first race, our telemetry feed has been analysed by the clever mashup coders out there. One of my favourites is OUseful.info.

This map shows the points in Bahrain where Hamilton hit 100% throttle!

And this beautiful layout shows which gear he was in as he did it.

It's a great little site, and I'm looking forward to see more insights into the data coming out. But it would be nice to see some copyright mentions shown for the data, as well as for the map itself.

In the next part in the series, I'll have a look at Load Testing.

Thanks for reading! I guess you could now share this post on TikTok or something. That'd be cool.
Or if you had any comments, you could find me on Threads.

Published