SharpGIS

#GIS from a .NET developer's perspective

Differential GPS using RTCM from NTRIP

This post will focus on how to get data from a NTRIP RTCM datastream. RTCM can greatly enhance the accuracy of your GPS receiver by downloading live correction data from the Internet using the NTRIP protocol. This example has been tested on Pocket PC 2002, but should work any other .NET capable OS as well.

The NTRIP data stream is basically an ordinary HTTP stream. My initial thought was just to use .NET's System.Net.WebRequest class to download the stream, but I quickly ended up with an infinite loop. The reason for this, is that the NTRIP stream never ends, and the WebRequest therefore never finishes.

Instead we have to do a bit more work ourselves. Luckily we have System.Net.Sockets to helps us out here. Lets initialize the socket, by calling a server at IP address '129.217.182.51' through port 80:

IPAddress BroadCasterIP = IPAddress.Parse("129.217.182.51");
int BroadCasterPort = 80;
 Socket sckt = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
 sckt.Blocking = true;
 sckt.Connect(new IPEndPoint(BroadCasterIP,BroadCasterPort));

The next thing we will have to do, is to send a request to the server, telling them what we want. In this case I'm requesting the datastream "FLEN0".

string msg = "GET /FLEN0 HTTP/1.1\r\n";
 msg += "User-Agent: NTRIP iter.dk\r\n";
 msg += "Accept: */*\r\nConnection: close\r\n";
 msg += "\r\n";

If the stream uses authentification, we would need to add the following, where username and password are strings containing, well... the username and password (surprise!). We need to encode the username and password to Base64 as well. A small funktion is provided for this. The request will then look like this:

string auth = ToBase64(username + ":" + password);
 string msg = "GET /FLEN0 HTTP/1.1\r\n";
 msg += "User-Agent: NTRIP iter.dk\r\n";
 msg += "Authorization: Basic " + auth + "\r\n";
 msg += "Accept: */*\r\nConnection: close\r\n";
 msg += "\r\n";
 [...]
 private string ToBase64(string str) {
   Encoding asciiEncoding = Encoding.ASCII;
   byte[] byteArray = new byte[asciiEncoding.GetByteCount(str)];
   byteArray = asciiEncoding.GetBytes(str);
   return Convert.ToBase64String(byteArray,0,byteArray.Length);
}

OK, now lets send the request:

byte[] data = System.Text.Encoding.ASCII.GetBytes(msg);
 sckt.Send(data);

Well now two things might happen. Either we start receiving the NTRIP RTCM stream, OR if we made some kind of error, we will receive a list of available data streams instead. I will not cover how to decode the data, but just show you how to pass the data on to your GPS. It's actually pretty straight forward. First of all, to receive the data, you can use the Sockets.Receive method:

byte[] returndata = new byte[256];
 sckt.Receive(returndata);

If the data returned is valid RTCM you can just throw it out to your serial port and directly on to the GPS device. Using the PocketGpsLib that is described elsewhere on this site, you would just write:

GPSHandler GPS = new GPSHandler(this); //Initialize GPS handler
//Insert code to set up the GPS here...
// [...]
if(GPS.IsPortOpen) { GPS.WriteToGPS(returndata); //Send RTCM data to GPS }

Now to make this really work, you would create a timer that with a short interval checked the socket for new data, and pass it on to the GPS device. I used an interval of 100ms, which seemed to work quite well.

When you are done using the socket, remember to close it again:

sckt.Shutdown(SocketShutdown.Both);
 sckt.Close();

Click here to view an example of how to implement the above. Note: This is not a full application. You still have to do a little work yourselves, but hopefully this should get you going.