It’s a Small World, After All, part 2 – VB, C#, and GPS (Matt Gertz)

In my previous post, we fixed up a C# GPS library to provide more support, and wrote all of the UI for a VB GPS application, all based on (but modified from) a Mobile GPS sample in the Windows Mobile 6.0 SDK.  In this post, we’ll finish up the app by enabling a bunch of cool functionality not exposed in the original sample.

The C# sample uses a helper function called UpdateData – I will too (as noted above), except that the code is going to deviate significantly.  We’ll start out by checking is the GPS is actually running, just in case we called outside of an event:

    Protected Sub UpdateData(ByVal sender As Object, ByVal args As System.EventArgs)

        If vbgps.Opened Then

 

First, we’ll update the screen with whatever cached device data we have:

            If device IsNot Nothing Then

                Me.Text = “VBGPS: “ & device.FriendlyName.ToString

                Me.StatusLabel.Text = device.DeviceState.ToString

            End If

 

This will change the title bar to include the name of the GPS device in use (in case you have multiple devices) and will set the StatusLabel to whatever the state of the GPS is (e.g., “On”).

All other interesting information comes from the cached position object:

            If position IsNot Nothing Then

 

We’ll start with the altitude.  There are two ways of calculating altitude – sea level (self-explanatory), and ellipsoid (which calculates altitude against a “perfect” ellipsoid representation of the otherwise pear-shaped earth).  We’re going to go with ellipsoid.  We’ll need to check if the information for it is reported as being valid, and if so, assigned the value to the appropriate label.  The value is returned to us in meters, and we’ll also show it in feet by multiplying the result by 3.281 feet/meters.  Again, we’ll format the results so that we only have two decimal places:

                If position.EllipsoidAltitudeValid Then

                    Me.AltLabel.Text = CDbl(position.EllipsoidAltitude).ToString(“####0.00″) _

                     & ” m (“ & CDbl(position.EllipsoidAltitude * 3.281).ToString(“####0.00″) _

 & “ft)”

                End If

 

Next is velocity.  The speed value will be in meters per second; We’ll show it in kph and mph.  I’ll also show the heading (if valid), and separate the two by an “@” sign (e.g., “88.00 kph (54.69 mph) @ 45.23°”:

                If position.SpeedValid Then

                    Me.VelLabel.Text = CDbl(position.Speed * 1.852).ToString(“###0.00″) _

& ” kph (“ & CDbl(position.Speed * 1.151).ToString(“###0.00″) & ” mph)”

                    If position.HeadingValid Then

                        Me.VelLabel.Text = Me.VelLabel.Text & ” @ “ _

& position.Heading.ToString(“##0.00″) & “°”

                    End If

                End If

 

Latitude and longitude are next.  We’ll be showing them in both DMS and DM format, using the methods we wrote in C#.  The only interesting thing here is converting negative values to W or S indicators:

                If position.LatitudeValid Then

                    Me.LatLabel.Text = position.LatitudeInDegreesMinutesSeconds.DMSString() _

& ” (“ & position.LatitudeInDegreesMinutesSeconds.DMString & “)”

                    If position.Latitude < 0 Then

                        Me.LatLabel.Text = Me.LatLabel.Text & ” S”

                    Else

                        Me.LatLabel.Text = Me.LatLabel.Text & ” N”

                    End If

                End If

 

                If position.LongitudeValid Then

                    Me.LongLabel.Text = position.LongitudeInDegreesMinutesSeconds.DMSString() _

& ” (“ & position.LongitudeInDegreesMinutesSeconds.DMString & “)”

                    If position.Longitude < 0 Then

                        Me.LongLabel.Text = Me.LongLabel.Text & ” W”

                    Else

                        Me.LongLabel.Text = Me.LongLabel.Text & ” E”

                    End If

                End If

 

Satellites are a bit more complicated, and if you do a straight port of the C# sample, you’ll get runtime errors.  This is because the C# code references values which may be NULL even if the values are valid – my VB code checks to see if the values are Nothing before referencing them.  (A value of Nothing is equivalent to zero satellites in this case, since the C# library uses the existence and size of the satellite array to generate a value.) 

There are three satellite components that we need to use – the number of satellites used to create a positioning solution, the number of them in view, and the total count of satellites – the resulting string should look something like (for example) “4/7 (8)”, depending on the actual number of satellites involved.

                If position.SatellitesInSolutionValid AndAlso _

                    position.SatellitesInViewValid AndAlso _

                    position.SatelliteCountValid Then

                    Dim SatSol As Satellite() = position.GetSatellitesInSolution()

                    Dim SatView As Satellite() = position.GetSatellitesInView()

                    Dim SatStr As String

                    If SatSol IsNot Nothing Then

                        SatStr = SatSol.Length & “/”

                    Else

                        SatStr = “0/”

                    End If

                    If SatView IsNot Nothing Then

                        SatStr += SatView.Length & ” (“

                    Else

                        SatStr += “0 (“

                    End If

                    Me.SatLabel.Text = SatStr & position.SatelliteCount & “)”

                End If

 

You can actually get more information on each satellite (such as its location in orbit, etc.) simply by exploring the methods and fields on the satellite object, but for now this will do fine for our project.

 Now that we’ve shown the information as to where we are, we need to tell the user how to get to where they are going.  Creating maps and routes is just a bit beyond the scope of this blog, but we can certainly indicate direction and distance.  Let’s assume the existence of a helper function called UpdateTargetInfo at this point – we’ll define it later:

                UpdateTargetInfo()