技术开发 频道

WM平台上如何开发出自己的GPS导航

  【IT168技术】现在GPS应用必须足以在商业环境如汽车导航中使用,此外,该如何解释GPS数据的实际工作过程,在这三个部分组成的系列,我将介绍两个主题,在大多数行业工程有GPS设备的今天,增加你编写一个商业级GPS应用的技巧。

  一个强大的语句

  这系列中的第一部分的任务将探讨解析原始GPS数据。幸运的是,任务是简化国家海洋电子协会由于它采用了一种行业标准,现在使用绝大多数的GPS设备。为了给开发人员提供一个良好的开端,我选择使用一些Visual Studio。NET源代码来自我的“GPS.NET全球定位SDK的”组件。 (代码被剥离,如多线程和错误处理功能。)

  NMEA数据发送以逗号分隔的“句子”,其中载有关于这句话的第一个字的信息。有超过50多种的句子,但翻译完成这项工作真只需要处理其中的一些。所有最常见的NMEA语句是一句是“Recommended Minimum”这一句,以“$GPRMC开头”。下面是一个例子:

  代码:

1 $GPRMC,040302.663,A,3939.7,N,10506.6,W,0.27,358.86,200804,,*1A

  这一个句子包含几乎所有的GPS应用程序需要:纬度,经度,速度,轴承,卫星获取的时间,固定的地位和磁性的变化。

  解析器的核心

  做NMEA翻译的第一步是写一个方法来做这两件事情:将每一句分离成单个字、审议第一个字,找出哪些信息是可以进一步提取。列表1-1显示了翻译类的开始。

  代码片段:

1 '*******************************************************
2
3 '**  Listing 1-1.  The core of an NMEA interpreter
4
5 '*******************************************************
6
7 Public Class NmeaInterpreter
8   ' Processes information from the GPS receiver
9   Public Function Parse(ByVal sentence As String) As Boolean
10     ' Divide the sentence into words
11     Dim Words() As String = GetWords(sentence)
12     ' Look at the first word to decide where to go next
13     Select Case Words(0)
14       Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
15         ' Indicate that the sentence was recognized
16         Return True
17       Case Else
18         ' Indicate that the sentence was not recognized
19         Return False
20     End Select
21   End Function
22   ' Divides a sentence into individual words
23   Public Function GetWords(ByVal sentence As String) As String()
24     Return sentence.Split(","c)
25   End Function
26 End Class
27

  下一步是执行实际信息的提取,首先是经度和纬度。纬度和经度以“DDD°MM’SS.S”的形式存储,其中D代表小时(也称为“度”),M代表分钟,S代表秒。坐标可以在速记上显示,如“DD°MM.M’” 甚至是 “DD°”。这句话的第四个单词“3939.7”,显示了当前的纬度为小时和分钟(39 ° 39.7')。前两个字符(39)代表小时,这个词其余部分(39.7)代表分钟。经度和纬度有相同的结构方式,除了前三个字符代表小时(105 ° 06.6')。关键词5和7表明“半球”,其中“N”是指“北”,“W”是指“西”等。半球附加到数字的末尾部分,做一个完整的测量。我发现 NMEA解析器 正像是事件驱动一样更容易协作。这是因为数据的到达没有特定的顺序。事件驱动类给应用程序的解析器最大的灵活性和响应能力。因此,我将设计解析器用来报告信息使用事件。第一个事件,PositionReceived,将会被凸起 只要目前的经度和纬度被收到。列表1-2扩大解析器用以记录目前的情况。

  代码片段:

1 '*******************************************************
2
3 '**  Listing 1-2.  Extracting information from a sentence
4
5 '*******************************************************
6
7 Public Class NmeaInterpreter
8   ' Raised when the current location has changed
9   Public Event PositionReceived(ByVal latitude As String, _
10                                 ByVal longitude As String)
11   ' Processes information from the GPS receiver
12   Public Function Parse(ByVal sentence As String) As Boolean
13     ' Look at the first word to decide where to go next
14     Select Case GetWords(sentence)(0)
15       Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
16         Return ParseGPRMC(sentence)
17       Case Else
18         ' Indicate that the sentence was not recognized
19         Return False
20     End Select
21   End Function
22   ' Divides a sentence into individual words
23   Public Function GetWords(ByVal sentence As String) As String()
24     Return sentence.Split(","c)
25   End Function
26   ' Interprets a $GPRMC message
27   Public Function ParseGPRMC(ByVal sentence As String) As Boolean
28     ' Divide the sentence into words
29     Dim Words() As String = GetWords(sentence)
30     ' Do we have enough values to describe our location?
31     If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
32                                 Words(6) <> "" Then
33       ' Yes. Extract latitude and longitude
34       Dim Latitude As String = Words(3).Substring(0, 2) & "°" ' Append hours
35       Latitude = Latitude & Words(3).Substring(2) & """"      ' Append minutes
36       Latitude = Latitude & Words(4)     ' Append the hemisphere
37       Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' Append hours
38       Longitude = Longitude & Words(5).Substring(3) & """"     ' Append minutes
39       Longitude = Longitude & Words(6)     ' Append the hemisphere
40       ' Notify the calling application of the change
41       RaiseEvent PositionReceived(Latitude, Longitude)
42     End If
43     ' Indicate that the sentence was recognized
44     Return True
45   End Function
46 End Class
47

  这里值得注意的一个地方就是在没有获取到信息时,某些GPS设备将记录空值。因此,一个好主意就是在解析之前来测试每个单词的值。如果您需要输入度数符号(°),按住Alt键并键入数字键盘上的“0176”。

  取出垃圾

  校验和以美元符号和星号(但不包括)之间的XOR字节来计算。这个校验和然后与语句中的校验和进行比较。如果校验和不匹配,这句话通常被丢弃。这是正常的,因为这样做GPS设备往往每隔几秒钟重复相同的信息。有比较校验和的能力,解析器能够抛出任何带有无效的校验和的语句。列表1-3扩大解析器:

  代码片段:

1 *******************************************************
2
3 '**  Listing 1-3.  Detecting and handling NMEA errors
4
5 '*******************************************************
6
7 Public Class NmeaInterpreter
8   ' Raised when the current location has changed
9   Public Event PositionReceived(ByVal latitude As String, _
10                                 ByVal longitude As String)
11   ' Processes information from the GPS receiver
12   Public Function Parse(ByVal sentence As String) As Boolean
13     ' Discard the sentence if its checksum does not match our calculated
14     'checksum
15     If Not IsValid(sentence) Then Return False
16     ' Look at the first word to decide where to go next
17     Select Case GetWords(sentence)(0)
18       Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
19         Return ParseGPRMC(sentence)
20       Case Else
21         ' Indicate that the sentence was not recognized
22         Return False
23     End Select
24   End Function
25   ' Divides a sentence into individual words
26   Public Function GetWords(ByVal sentence As String) As String()
27     Return sentence.Split(","c)
28   End Function
29   ' Interprets a $GPRMC message
30   Public Function ParseGPRMC(ByVal sentence As String) As Boolean
31     ' Divide the sentence into words
32     Dim Words() As String = GetWords(sentence)
33     ' Do we have enough values to describe our location?
34     If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
35                                 Words(6) <> "" Then
36       ' Yes. Extract latitude and longitude
37       Dim Latitude As String = Words(3).Substring(0, 2) & "°" ' Append hours
38       Latitude = Latitude & Words(3).Substring(2) & """"      ' Append minutes
39       Latitude = Latitude & Words(4)     ' Append the hemisphere
40       Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' Append hours
41       Longitude = Longitude & Words(5).Substring(3) & """"     ' Append minutes
42       Longitude = Longitude & Words(6)     ' Append the hemisphere
43       ' Notify the calling application of the change
44       RaiseEvent PositionReceived(Latitude, Longitude)
45     End If
46     ' Indicate that the sentence was recognized
47     Return True
48   End Function
49   ' Returns True if a sentence's checksum matches the calculated checksum
50   Public Function IsValid(ByVal sentence As String) As Boolean
51     ' Compare the characters after the asterisk to the calculation
52     Return sentence.Substring(sentence.IndexOf("*") + 1) = GetChecksum(sentence)
53   End Function
54   ' Calculates the checksum for a sentence
55   Public Function GetChecksum(ByVal sentence As String) As String
56     ' Loop through all chars to get a checksum
57     Dim Character As Char
58     Dim Checksum As Integer
59     For Each Character In sentence
60       Select Case Character
61         Case "$"c
62           ' Ignore the dollar sign
63         Case "*"c
64           ' Stop processing before the asterisk
65           Exit For
66         Case Else
67           ' Is this the first value for the checksum?
68           If Checksum = 0 Then
69             ' Yes. Set the checksum to the value
70             Checksum = Convert.ToByte(Character)
71           Else
72             ' No. XOR the checksum with this character's value
73             Checksum = Checksum Xor Convert.ToByte(Character)
74           End If
75       End Select
76     Next
77     ' Return the checksum formatted as a two-character hexadecimal
78     Return Checksum.ToString("X2")
79   End Function
80 End Class
81

  无线原子时

  时间是GPS技术的基石,因为距离以光速来测量。每个GPS卫星载有4个原子钟,它用来测定几纳秒内的无线传输。一个有趣的特点是只需几行代码,这些原子钟可用于同步电脑毫秒级精确度的时钟。$GPRMC语句的第二字,“040302.663”,以压缩格式包含卫星导出的时间。前两个字符代表时,紧接着两个字符代表分钟,再接着两个代表秒,小数点后的一切代表毫秒。因此,时间是上午4:03:02.663。然而,卫星报告的时间为通用时间(GMT +0),所以时间必须适应当地的时区。列表1-4增加了对卫星导出时间的支持,并使用DateTime.ToLocalTime方法将卫星时间转换为本地时区。

  代码片段:

  1 ********************************************************
  2
  3 '**  Listing 1-4.  Add support for satellite-derived time
  4
  5 '********************************************************
  6
  7 Public Class NmeaInterpreter
  8   ' Raised when the current location has changed
  9   Public Event PositionReceived(ByVal latitude As String, _
10                                 ByVal longitude As String)
11   Public Event DateTimeChanged(ByVal dateTime As DateTime)
12   ' Processes information from the GPS receiver
13   Public Function Parse(ByVal sentence As String) As Boolean
14     ' Discard the sentence if its checksum does not match our
15     ' calculated checksum
16     If Not IsValid(sentence) Then Return False
17     ' Look at the first word to decide where to go next
18     Select Case GetWords(sentence)(0)
19       Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
20         Return ParseGPRMC(sentence)
21       Case Else
22         ' Indicate that the sentence was not recognized
23         Return False
24     End Select
25   End Function
26   ' Divides a sentence into individual words
27   Public Function GetWords(ByVal sentence As String) As String()
28     Return sentence.Split(","c)
29   End Function
30   ' Interprets a $GPRMC message
31   Public Function ParseGPRMC(ByVal sentence As String) As Boolean
32     ' Divide the sentence into words
33     Dim Words() As String = GetWords(sentence)
34     ' Do we have enough values to describe our location?
35     If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
36                                 Words(6) <> "" Then
37       ' Yes. Extract latitude and longitude
38       Dim Latitude As String = Words(3).Substring(0, 2) & "°" ' Append hours
39       Latitude = Latitude & Words(3).Substring(2) & """"    ' Append minutes
40       Latitude = Latitude & Words(4)     ' Append the hemisphere
41       Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' Append hours
42       Longitude = Longitude & Words(5).Substring(3) & """"    ' Append minutes
43       Longitude = Longitude & Words(6)     ' Append the hemisphere
44       ' Notify the calling application of the change
45       RaiseEvent PositionReceived(Latitude, Longitude)
46     End If
47     ' Do we have enough values to parse satellite-derived time?
48     If Words(1) <> "" Then
49       ' Yes. Extract hours, minutes, seconds and milliseconds
50       Dim UtcHours As Integer = CType(Words(1).Substring(0, 2), Integer)
51       Dim UtcMinutes As Integer = CType(Words(1).Substring(2, 2), Integer)
52       Dim UtcSeconds As Integer = CType(Words(1).Substring(4, 2), Integer)
53       Dim UtcMilliseconds As Integer
54       ' Extract milliseconds if it is available
55       If Words(1).Length > 7 Then
56           UtcMilliseconds = CType(Single.Parse(Words(1).Substring(6), _
57               CultureInfo.InvariantCulture) * 1000, Integer)
58       End If
59       ' Now build a DateTime object with all values
60       Dim Today As DateTime = System.DateTime.Now.ToUniversalTime
61       Dim SatelliteTime As New System.DateTime(Today.Year, Today.Month, _
62         Today.Day, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds)
63       ' Notify of the new time, adjusted to the local time zone
64       RaiseEvent DateTimeChanged(SatelliteTime.ToLocalTime)
65     End If
66     ' Indicate that the sentence was recognized
67     Return True
68   End Function
69   ' Returns True if a sentence's checksum matches the calculated checksum
70   Public Function IsValid(ByVal sentence As String) As Boolean
71     ' Compare the characters after the asterisk to the calculation
72     Return sentence.Substring(sentence.IndexOf("*") + 1) = _
73                                        GetChecksum(sentence)
74   End Function
75   ' Calculates the checksum for a sentence
76   Public Function GetChecksum(ByVal sentence As String) As String
77     ' Loop through all chars to get a checksum
78     Dim Character As Char
79     Dim Checksum As Integer
80     For Each Character In sentence
81       Select Case Character
82         Case "$"c
83           ' Ignore the dollar sign
84         Case "*"c
85           ' Stop processing before the asterisk
86           Exit For
87         Case Else
88           ' Is this the first value for the checksum?
89           If Checksum = 0 Then
90             ' Yes. Set the checksum to the value
91             Checksum = Convert.ToByte(Character)
92           Else
93             ' No. XOR the checksum with this character's value
94             Checksum = Checksum Xor Convert.ToByte(Character)
95           End If
96       End Select
97     Next
98     ' Return the checksum formatted as a two-character hexadecimal
99     Return Checksum.ToString("X2")
100   End Function
101 End Class
102

  方向和速度提醒

  GPS设备分析您的位置,随着时间的推移来计算速度和影响。在本文开头$ GPRMC语句也包括这些数据。速度在每个节点都是始终要记录的,轴承以“方位”来记录,从0 °到360 °顺时针其中0 °表示北, 90 °表示东等。因此在地平线上测量。要应用数学公式转换成英里每小时。全球定位系统的力量再一次证明了一行代码。表单1-5的数字,显示汽车是否超过时速限制。

  代码片段:

  1 '*******************************************************
  2
  3 '**  Listing 1-5.  Extracting speed and bearing
  4
  5 '*******************************************************
  6
  7 Public Class NmeaInterpreter
  8   ' Raised when the current location has changed
  9   Public Event PositionReceived(ByVal latitude As String, _
10                                 ByVal longitude As String)
11   Public Event DateTimeChanged(ByVal dateTime As DateTime)
12   Public Event BearingReceived(ByVal bearing As Double)
13   Public Event SpeedReceived(ByVal speed As Double)
14   Public Event SpeedLimitReached()
15   ' Processes information from the GPS receiver
16   Public Function Parse(ByVal sentence As String) As Boolean
17     ' Discard the sentence if its checksum does not match our calculated
18     ' checksum
19     If Not IsValid(sentence) Then Return False
20     ' Look at the first word to decide where to go next
21     Select Case GetWords(sentence)(0)
22       Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
23         Return ParseGPRMC(sentence)
24       Case Else
25         ' Indicate that the sentence was not recognized
26         Return False
27     End Select
28   End Function
29   ' Divides a sentence into individual words
30   Public Function GetWords(ByVal sentence As String) As String()
31     Return sentence.Split(","c)
32   End Function
33 ' Interprets a $GPRMC message
34 Public Function ParseGPRMC(ByVal sentence As String) As Boolean
35     ' Divide the sentence into words
36     Dim Words() As String = GetWords(sentence)
37     ' Do we have enough values to describe our location?
38     If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
39                                 Words(6) <> "" Then
40       ' Yes. Extract latitude and longitude
41       Dim Latitude As String = Words(3).Substring(0, 2) & "°" ' Append hours
42       Latitude = Latitude & Words(3).Substring(2) & """"    ' Append minutes
43       Latitude = Latitude & Words(4)     ' Append the hemisphere
44       Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' Append hours
45       Longitude = Longitude & Words(5).Substring(3) & """"    ' Append minutes
46       Longitude = Longitude & Words(6)     ' Append the hemisphere
47       ' Notify the calling application of the change
48       RaiseEvent PositionReceived(Latitude, Longitude)
49     End If
50     ' Do we have enough values to parse satellite-derived time?
51     If Words(1) <> "" Then
52       ' Yes. Extract hours, minutes, seconds and milliseconds
53       Dim UtcHours As Integer = CType(Words(1).Substring(0, 2), Integer)
54       Dim UtcMinutes As Integer = CType(Words(1).Substring(2, 2), Integer)
55       Dim UtcSeconds As Integer = CType(Words(1).Substring(4, 2), Integer)
56       Dim UtcMilliseconds As Integer
57       ' Extract milliseconds if it is available
58       If Words(1).Length > 7 Then UtcMilliseconds = _
59            CType(Single.Parse(Words(1).Substring(6), _
60                 CultureInfo.InvariantCulture) * 1000, Integer)
61       ' Now build a DateTime object with all values
62       Dim Today As DateTime = System.DateTime.Now.ToUniversalTime
63       Dim SatelliteTime As New System.DateTime(Today.Year, Today.Month, _
64         Today.Day, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds)
65       ' Notify of the new time, adjusted to the local time zone
66       RaiseEvent DateTimeChanged(SatelliteTime.ToLocalTime)
67     End If
68     ' Do we have enough information to extract the current speed?
69     If Words(7) <> "" Then
70       ' Yes.  Convert it into MPH
71       Dim Speed As Double = CType(Words(7), Double) * 1.150779
72       ' If we're over 55MPH then trigger a speed alarm!
73       If Speed > 55 Then RaiseEvent SpeedLimitReached()
74       ' Notify of the new speed
75       RaiseEvent SpeedReceived(Speed)
76     End If
77     ' Do we have enough information to extract bearing?
78     If Words(8) <> "" Then
79       ' Indicate that the sentence was recognized
80       Dim Bearing As Double = CType(Words(8), Double)
81       RaiseEvent BearingReceived(Bearing)
82     End If
83     ' Indicate that the sentence was recognized
84     Return True
85   End Function
86   ' Returns True if a sentence's checksum matches the calculated checksum
87   Public Function IsValid(ByVal sentence As String) As Boolean
88     ' Compare the characters after the asterisk to the calculation
89     Return sentence.Substring(sentence.IndexOf("*") + 1) = _
90                                         GetChecksum(sentence)
91   End Function
92   ' Calculates the checksum for a sentence
93   Public Function GetChecksum(ByVal sentence As String) As String
94     ' Loop through all chars to get a checksum
95     Dim Character As Char
96     Dim Checksum As Integer
97     For Each Character In sentence
98       Select Case Character
99         Case "$"c
100           ' Ignore the dollar sign
101         Case "*"c
102           ' Stop processing before the asterisk
103           Exit For
104         Case Else
105           ' Is this the first value for the checksum?
106           If Checksum = 0 Then
107             ' Yes. Set the checksum to the value
108             Checksum = Convert.ToByte(Character)
109           Else
110             ' No. XOR the checksum with this character's value
111             Checksum = Checksum Xor Convert.ToByte(Character)
112           End If
113       End Select
114     Next
115     ' Return the checksum formatted as a two-character hexadecimal
116     Return Checksum.ToString("X2")
117   End Function
118 End Class
119

  目前是否有 Fix

  $ GPRMC语句包含一个值,显示“Fix”是否已经获得。当至少三颗卫星的信号强度足以与计算您的位置有关一个修复程序时,Fix将会获得。如果至少有四颗卫星都参与,高度也成为众所周知的。$ GPRMC语句的第三个字是两个字母中的一个:“A”为“积极”,其中获得一个Fix,或“V”为“无效”目前没有Fix存在。列表1-6包括代码审查这一字母和修复情况的报告。

  代码片段:

  1 *******************************************************
  2
  3 '**  Listing 1-6.  Extracting satellite fix status
  4
  5 '*******************************************************
  6
  7 Public Class NmeaInterpreter
  8
  9   ' Raised when the current location has changed
10   Public Event PositionReceived(ByVal latitude As String, _
11                                 ByVal longitude As String)
12   Public Event DateTimeChanged(ByVal dateTime As DateTime)
13   Public Event BearingReceived(ByVal bearing As Double)
14   Public Event SpeedReceived(ByVal speed As Double)
15   Public Event SpeedLimitReached()
16   Public Event FixObtained()
17   Public Event FixLost()
18   ' Processes information from the GPS receiver
19   Public Function Parse(ByVal sentence As String) As Boolean
20     ' Discard the sentence if its checksum does not match our calculated
21     ' checksum
22     If Not IsValid(sentence) Then Return False
23     ' Look at the first word to decide where to go next
24     Select Case GetWords(sentence)(0)
25       Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
26         Return ParseGPRMC(sentence)
27       Case Else
28         ' Indicate that the sentence was not recognized
29         Return False
30     End Select
31   End Function
32   ' Divides a sentence into individual words
33   Public Function GetWords(ByVal sentence As String) As String()
34     Return sentence.Split(","c)
35   End Function
36 ' Interprets a $GPRMC message
37 Public Function ParseGPRMC(ByVal sentence As String) As Boolean
38     ' Divide the sentence into words
39     Dim Words() As String = GetWords(sentence)
40     ' Do we have enough values to describe our location?
41     If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
42                                 Words(6) <> "" Then
43       ' Yes. Extract latitude and longitude
44       Dim Latitude As String = Words(3).Substring(0, 2) & "°"  ' Append hours
45       Latitude = Latitude & Words(3).Substring(2) & """"    ' Append minutes
46       Latitude = Latitude & Words(4)     ' Append the hemisphere
47       Dim Longitude As String = Words(5).Substring(0, 3) & "°"  ' Append hours
48       Longitude = Longitude & Words(5).Substring(3) & """"    ' Append minutes
49       Longitude = Longitude & Words(6)     ' Append the hemisphere
50       ' Notify the calling application of the change
51       RaiseEvent PositionReceived(Latitude, Longitude)
52     End If
53     ' Do we have enough values to parse satellite-derived time?
54     If Words(1) <> "" Then
55       ' Yes. Extract hours, minutes, seconds and milliseconds
56       Dim UtcHours As Integer = CType(Words(1).Substring(0, 2), Integer)
57       Dim UtcMinutes As Integer = CType(Words(1).Substring(2, 2), Integer)
58       Dim UtcSeconds As Integer = CType(Words(1).Substring(4, 2), Integer)
59       Dim UtcMilliseconds As Integer
60       ' Extract milliseconds if it is available
61       If Words(1).Length > 7 Then UtcMilliseconds = _
62                 CType(Single.Parse(Words(1).Substring(6), _
63                      CultureInfo.InvariantCulture) * 1000, Integer)
64       ' Now build a DateTime object with all values
65       Dim Today As DateTime = System.DateTime.Now.ToUniversalTime
66       Dim SatelliteTime As New System.DateTime(Today.Year, Today.Month, _
67         Today.Day, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds)
68       ' Notify of the new time, adjusted to the local time zone
69       RaiseEvent DateTimeChanged(SatelliteTime.ToLocalTime)
70     End If
71     ' Do we have enough information to extract the current speed?
72     If Words(7) <> "" Then
73       ' Yes.  Convert it into MPH
74       Dim Speed As Double = CType(Words(7), Double) * 1.150779
75       ' If we're over 55MPH then trigger a speed alarm!
76       If Speed > 55 Then RaiseEvent SpeedLimitReached()
77       ' Notify of the new speed
78       RaiseEvent SpeedReceived(Speed)
79     End If
80     ' Do we have enough information to extract bearing?
81     If Words(8) <> "" Then
82       ' Indicate that the sentence was recognized
83       Dim Bearing As Double = CType(Words(8), Double)
84       RaiseEvent BearingReceived(Bearing)
85     End If
86     ' Does the device currently have a satellite fix?
87     If Words(2) <> "" Then
88       Select Case Words(2)
89         Case "A"
90           RaiseEvent FixObtained()
91         Case "V"
92           RaiseEvent FixLost()
93       End Select
94     End If
95     ' Indicate that the sentence was recognized
96     Return True
97   End Function
98   ' Returns True if a sentence's checksum matches the calculated checksum
99   Public Function IsValid(ByVal sentence As String) As Boolean
100     ' Compare the characters after the asterisk to the calculation
101     Return sentence.Substring(sentence.IndexOf("*") + 1) = GetChecksum(sentence)
102   End Function
103   ' Calculates the checksum for a sentence
104   Public Function GetChecksum(ByVal sentence As String) As String
105     ' Loop through all chars to get a checksum
106     Dim Character As Char
107     Dim Checksum As Integer
108     For Each Character In sentence
109       Select Case Character
110         Case "$"c
111           ' Ignore the dollar sign
112         Case "*"c
113           ' Stop processing before the asterisk
114           Exit For
115         Case Else
116           ' Is this the first value for the checksum?
117           If Checksum = 0 Then
118             ' Yes. Set the checksum to the value
119             Checksum = Convert.ToByte(Character)
120           Else
121             ' No. XOR the checksum with this character's value
122             Checksum = Checksum Xor Convert.ToByte(Character)
123           End If
124       End Select
125     Next
126     ' Return the checksum formatted as a two-character hexadecimal
127     Return Checksum.ToString("X2")
128   End Function
129 End Class
130
0
相关文章