HTTP Headers request reduction

The HTTP protocol is pretty light weight but in some cases the overhead can impact on performance\operational costs\scalability etc. So I fired up Fiddler to have a look at what was going on.

Request – Bytes Sent: 305
POST http://gpstrackerhttpheaders.cloudapp.net/posV1.aspx HTTP/1.1
x-DeviceMacAddress: 5C-86-4A-00-3F-63
x-3DFix: True
x-GPSTime: 2011 06 01 01:52:05
x-Latitude: -43.XXXXX
x-Longitude: 172.XXXXX
x-HDoP: 0.83
x-Altitude: 24.1
x-Speed: 0
x-Heading: 0
Content-Length: 0
Connection: Keep-Alive
Host: gpstrackerhttpheaders.cloudapp.net

Response – Bytes Received: 278
HTTP/1.1 200 OK
Cache-Control: private
Server: Microsoft-IIS/7.0
Set-Cookie: ASP.NET_SessionId=2giugnxvke4iv3vtekln1n0k; path=/; HttpOnly
x-UpdateIntervalSecs: 30
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 19 Jan 2013 10:00:49 GMT
Content-Length: 0

The first step was to shorten the header names (this could be taken to extremes with short names and a limited number of headers) which would reduce the size of the request and remove the ASP.Net session state information from the response.

Request – Bytes Sent: 263
POST http://gpstrackerhttpheaders.cloudapp.net/posV2.aspx HTTP/1.1
x-ID: 5C-86-4A-00-3F-63
x-3D: True
x-Time: 2011 06 01 02:16:26
x-Lat: -43.XXXXX
x-Lon: 172.XXXXX
x-HDoP: 0.92
x-Alt: 25.0
x-Spd: 1
x-Hdg: 0
Content-Length: 0
Connection: Keep-Alive
Host: gpstrackerhttpheaders.cloudapp.net

Response – Bytes Received: 217
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/7.0
x-UpdMin: 30
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 19 Jan 2013 10:25:12 GMT
Content-Length: 0

With minimal effort the payloads were reduced by roughly 90 bytes (V1 573 bytes V2 480 bytes),

HTTP Headers baseline

Using the HttpWebRequest functionality in system.http and using the HTTP headers to upload the GPS position data is a pretty simple and low code approach. For this initial version I’m uploading the

  • Device Mac Address
  • 2D vs 3D fix
  • Latitude
  • Longitude
  • Horizontal dilution of position (HDoP)
  • Altitude
  • Speed
  • Heading

The server responds with

  • Minimum time between position reports

This approach does have some disadvantages

Adding system.http increases the size of the download to by roughly 40K which on the Netduino Plus could be a problem. The HTTP requests and responses can also be a bit chunky. The HttpWebRequest.GetResponse call is synchronous which could cause some issues with the processing of the GPS NMEA data stream (particularly when there are connectivity problems).

I’ll be looking at solutions to these issues in future posts

Client application

using (HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(CloudServerUrl))
{
request.Method = "POST";
request.Headers.Add("x-DeviceMacAddress", DeviceMacAddress());
request.Headers.Add("x-3DFix", Gps.Fix3D.ToString());
request.Headers.Add("x-GPSTime", DateTime.Now.ToString("yyyy MM dd hh:mm:ss"));
request.Headers.Add("x-Latitude", Gps.Latitude.ToString("F5"));
request.Headers.Add("x-Longitude", Gps.Longitude.ToString("F5"));
request.Headers.Add("x-HDoP", Gps.HDoP.ToString("F2"));
request.Headers.Add("x-Altitude", Gps.Altitude.ToString("F1"));
request.Headers.Add("x-Speed", Gps.Kmh.ToString("F0"));
request.Headers.Add("x-Heading", Gps.TrackAngle.ToString("F0"));
request.ContentLength = 0;


using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Debug.Print(" HTTP Status:" + response.StatusDescription);

if (response.StatusCode == HttpStatusCode.OK)
{
if (response.Headers["x-UpdateIntervalSecs"] != null)
{
positionUpdateIntervalMinimum = new TimeSpan(0, 0, int.Parse(response.Headers["x-UpdateIntervalSecs"].ToString()));
}
}
}

On the server side

protected void Page_Load(object sender, EventArgs e)
{
if (this.Request.Headers["x-DeviceMacAddress"] == null)
{
return;
}
string deviceMacAddress = this.Request.Headers["x-DeviceMacAddress"];


if (this.Request.Headers["x-GPSTime"] == null)
{
return;
}
DateTime gpsTime = DateTime.ParseExact(this.Request.Headers["x-GPSTime"], "yyyy MM dd hh:mm:ss", CultureInfo.InvariantCulture);

if (this.Request.Headers["x-3DFix"] == null)
{
return;
}
bool is3DFix = bool.Parse(this.Request.Headers["x-3DFix"]);

if (this.Request.Headers["x-Latitude"] == null)
{
return;
}
Double latitude = Double.Parse(this.Request.Headers["x-Latitude"]);

if (this.Request.Headers["x-Longitude"] == null)
{
return;
}
Double longitude = Double.Parse(this.Request.Headers["x-Longitude"]);

if (this.Request.Headers["x-HDoP"] == null)
{
return;
}
Double hDoP = Double.Parse(this.Request.Headers["x-HDoP"]);

if (this.Request.Headers["x-Altitude"] == null)
{
return;
}
Double altitude = Double.Parse(this.Request.Headers["x-Altitude"]);

if (this.Request.Headers["x-Speed"] == null)
{
return;
}
int speed = int.Parse(this.Request.Headers["x-Speed"]);

if (this.Request.Headers["x-Heading"] == null)
{
return;
}
int heading = int.Parse(this.Request.Headers["x-Heading"]);

this.Response.Headers.Add("x-UpdateIntervalSecs", "30") ;
}

Source for HTTP Headers Client V1, and HTTP Headers ServiceV1

GPS Netduino Plus demo platform

For the initial posts the platform will be a Netduino Plus based and connected to the internet via cable. Once the application is robust enough I’ll take make it portable using a GSM Modem.

The BoM for the Netduino client posts is

Netduino Plus and GPS

NetMF cloud connectivity options

I do most of my dev work with NetMF devices and Windows Azure so I though it would be useful\interesting to explore the different cloud connectivity options.

I’ll start with the simplest possible HTTP based approach, look at how to reduce the device memory footprint, reduce traffic on the wire, secure the data, and take the solution mobile.

Then, as time allows I’ll build clients which use

The initial scenario is a GPS equiped NetMF device reporting position information to an application running in Windows Azure. Rather than reinventing the wheel I have used the NetMF Toolbox NMEA GPS module but have added HDoP reporting.

The samples will run on a Netduino, Netduino Plus or Fez Spider.

For the netduino based examples the BoM is