Mock LocationProvider - Structure/Explanation (NMEA, $GPRMC)
What is this: This tutorial shows how Mock LocationProviders are structured, so that you will be able to set up your own.
What you will learn: How a Mock LocationProvider (NMEA,$GPRMC) is built up.
Problems/Questions: post right below...
Difficulty: 2 of 5
Description:
Basically a mock (~= fake) location provider is simply a textfile with a list of (gps-)locations within.
Each Mock LocationProvider to be created needs its own directory in the following path on the emulator: Quote:
/data/misc/location/<provider_name>.
When an LocationProvider is requested its directory is searched for the following files (in order):
class
kml
nmea <--- This is explained here
track
1.
If you pull the file ("/data/app/misc/location/gps/nmea")(which is a such a mock location provider, as no gps-device can be attached) via Eclipse' DDMS-View from the emulator to your pc , you see the following:
Java:
$GPRMC,.......
$GPRMC,003347.000,A,3725.3433,N,12205.7920,W,0.08,149.46,061007,,,D*70
$GPRMC,003348.000,A,3725.3433,N,12205.7921,W,0.05,142.51,061007,,,D*7E
$GPRMC,003349.000,A,3725.3432,N,12205.7921,W,0.08,159.56,061007,,,D*7E
$GPRMC,003350.000,A,3725.3432,N,12205.7921,W,0.06,151.59,061007,,,D*7F
$GPRMC,003351.000,A,3725.3432,N,12205.7921,W,0.20,120.57,061007,,,D*72
$GPRMC,.......
If you then lookup that "$GPRMC"-String on Google you will see, that it is a part of the NMEA-Protocol (who could expect that ):
Quote:
$GPRMC - Recommended Minimum Specific GPS/TRANSIT Data
So '$GPRMC' indicates a simple/minimalistic "partition" of the NMEA-Protocol.
So as the most gps-devices emit those GPRMC-'setences' (one line is one sentence) Android simply parses them line by line.
Fine, but what the heck do all those numbers/characters mean :
If you really want to create you own Mock LocationProvider, take a look here for extensive explanation.
Quote:
* RMC
RMC = Recommended Minimum Specific GPS/TRANSIT Data
$GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh
1 = UTC(universal time, coordinated) of position fix
2 = Data status (A=good, V=navigation receiver warning)
3 = Current Latitude
4 = North/South in Latitude Hemisphere
5 = Current Longitude
6 = East/West in Longitude Hemisphere
7 = Speed over ground in knots
8 = (Direction of travel N:0°, E:90°, S:180°, W:270°)
9 = UT DateStamp
10 = Magnetic variation degrees (Easterly var. subtracts from true course)
11 = East/West
12 = Checksum
So lets parse one 'sentence' by hand to understand this:
XML:
$GPRMC,003347.000,A,3725.3433,N,12205.7920,W,0.08,149.46,061007,,,D*70
Parts:
1: 003347.000 --> 0:33 am 47 seconds 0 milliseconds (UTC(universal time, coordinated) of position fix)
2: A --> Status is ok (Data status (A=good, V=navigation receiver warning))
3: 3725.3433 (North/South in Latitude Hemisphere)
4: N --> North (North/South)
5: 12205.7920 (Current Longitude)
6: W --> West (East/West in Longitude Hemisphere)
7: 0.08 --> 0.08 knots/second (Direction: North/West) (Speed over ground in knots)
8: 149.46 --> sth. like SouthEast (Direction of travel N:0°, E:90°, S:180°, W:270°)
9: 061007 --> 6th October, 2007 (UT(universal time) DateStamp)
10: <empty> (Magnetic variation degrees (Easterly var. subtracts from true course))
11: <empty> (East/West)
12: D*70 (Checksum)
So if you want to create your own Mock LocationProvider, you will need to calculate the Checksum of each 'sentence'.
Example-Implementation in JAVA :
Java:
/** Calculates the checksum for a sentence */
public static String getChecksum(String sentence) {
// Loop through all chars to get a checksum
char character;
int checksum = 0;
int length = sentence.length();
for (int i = 0; i < length; i++) {
character = sentence.charAt(i);
switch (character) {
case '$':
// Ignore the dollar sign
break;
case '*':
// Stop processing before the asterisk
break;
default:
// Is this the first value for the checksum?
if (checksum == 0) {
// Yes. Set the checksum to the value
checksum = (byte) character;
} else {
// No. XOR the checksum with this character's value
checksum = checksum ^ ((byte) character);
}
}
}
// Return the checksum formatted as a two-character hexadecimal
return Integer.toHexString(checksum);
}
Example-Implementation in VB.NET :
VB.NET:
' Calculates the checksum for a sentence
Public Function GetChecksum(ByVal sentence As String) As String
' Loop through all chars to get a checksum
Dim Character As Char
Dim Checksum As Integer
For Each Character In sentence
Select Case Character
Case "$"c
' Ignore the dollar sign
Case "*"c
' Stop processing before the asterisk
Exit For
Case Else
' Is this the first value for the checksum?
If Checksum = 0 Then
' Yes. Set the checksum to the value
Checksum = Convert.ToByte(Character)
Else
' No. XOR the checksum with this character's value
Checksum = Checksum Xor Convert.ToByte(Character)
End If
End Select
Next
' Return the checksum formatted as a two-character hexadecimal
Return Checksum.ToString("X2")
End Function
Feel free to ask, if any question is still open