Skip to content

Commit

Permalink
Merge 28c753a into c227bc3
Browse files Browse the repository at this point in the history
  • Loading branch information
icholy committed Mar 16, 2018
2 parents c227bc3 + 28c753a commit 9fb5bf4
Show file tree
Hide file tree
Showing 31 changed files with 1,031 additions and 999 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ install:

script:
- go vet -x ./...
- $HOME/gopath/bin/golint ./...
- $HOME/gopath/bin/golint -set_exit_status ./...
- go test -v ./...
- go test -covermode=count -coverprofile=profile.cov .

Expand Down
102 changes: 20 additions & 82 deletions glgsv.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package nmea

import (
"fmt"
"strconv"
)

const (
// PrefixGLGSV prefix
PrefixGLGSV = "GLGSV"
Expand All @@ -13,12 +8,11 @@ const (
// GLGSV represents the GPS Satellites in view
// http://aprs.gids.nl/nmea/#glgsv
type GLGSV struct {
Sentence
TotalMessages int64 // Total number of messages of this type in this cycle
MessageNumber int64 // Message number
NumberSVsInView int64 // Total number of SVs in view

Info []GLGSVInfo // visible satellite info (0-4 of these)
Sent
TotalMessages int64 // Total number of messages of this type in this cycle
MessageNumber int64 // Message number
NumberSVsInView int64 // Total number of SVs in view
Info []GLGSVInfo // visible satellite info (0-4 of these)
}

// GLGSVInfo represents information about a visible satellite
Expand All @@ -30,80 +24,24 @@ type GLGSVInfo struct {
}

// NewGLGSV constructor
func NewGLGSV(sentence Sentence) GLGSV {
return GLGSV{Sentence: sentence}
}

// GetSentence getter
func (s GLGSV) GetSentence() Sentence {
return s.Sentence
}

func (s *GLGSV) parse() error {
if s.Type != PrefixGLGSV {
return fmt.Errorf("%s is not a %s", s.Type, PrefixGLGSV)
}
var err error
if s.Fields[0] != "" {
s.TotalMessages, err = strconv.ParseInt(s.Fields[0], 10, 64)
if err != nil {
return fmt.Errorf("GLGSV decode total number of messages error: %s", s.Fields[0])
}
}

if s.Fields[1] != "" {
s.MessageNumber, err = strconv.ParseInt(s.Fields[1], 10, 64)
if err != nil {
return fmt.Errorf("GLGSV decode message number error: %s", s.Fields[1])
}
func NewGLGSV(s Sent) (GLGSV, error) {
p := newParser(s, PrefixGLGSV)
m := GLGSV{
Sent: s,
TotalMessages: p.Int64(0, "total number of messages"),
MessageNumber: p.Int64(1, "message number"),
NumberSVsInView: p.Int64(2, "number of SVs in view"),
}

if s.Fields[2] != "" {
s.NumberSVsInView, err = strconv.ParseInt(s.Fields[2], 10, 64)
if err != nil {
return fmt.Errorf("GLGSV decode number of SVs in view error: %s", s.Fields[2])
}
}

s.Info = nil
for i := 0; i < 4; i++ {
if 5*i+4 > len(s.Fields) {
if 5*i+4 > len(m.Fields) {
break
}
info := GLGSVInfo{}
field := s.Fields[3+i*4]
if s.Fields[3+i*4] != "" {
info.SVPRNNumber, err = strconv.ParseInt(field, 10, 64)
if err != nil {
return fmt.Errorf("GLGSV decode SV prn number error: %s", field)
}
}

field = s.Fields[4+i*4]
if field != "" {
info.Elevation, err = strconv.ParseInt(field, 10, 64)
if err != nil {
return fmt.Errorf("GLGSV decode elevation error: %s", field)
}
}

field = s.Fields[5+i*4]
if field != "" {
info.Azimuth, err = strconv.ParseInt(field, 10, 64)
if err != nil {
return fmt.Errorf("GLGSV decode azimuth error: %s", field)
}
}

field = s.Fields[6+i*4]
if field != "" {
info.SNR, err = strconv.ParseInt(field, 10, 64)
if err != nil {
return fmt.Errorf("GLGSV decode SNR error: %s", field)
}
}
s.Info = append(s.Info, info)
m.Info = append(m.Info, GLGSVInfo{
SVPRNNumber: p.Int64(3+i*4, "SV prn number"),
Elevation: p.Int64(4+i*4, "elevation"),
Azimuth: p.Int64(5+i*4, "azimuth"),
SNR: p.Int64(6+i*4, "SNR"),
})
}

return nil
return m, p.Err()
}
26 changes: 12 additions & 14 deletions glgsv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestGLGSVGoodSentence(t *testing.T) {
s, err := Parse(goodMsg)

assert.NoError(t, err, "Unexpected error parsing good sentence")
assert.Equal(t, PrefixGLGSV, s.GetSentence().Type, "Prefix does not match")
assert.Equal(t, PrefixGLGSV, s.Prefix(), "Prefix does not match")

sentence := s.(GLGSV)
assert.Equal(t, int64(3), sentence.TotalMessages, "Total messages does not match")
Expand Down Expand Up @@ -44,7 +44,7 @@ func TestGLGSVShort(t *testing.T) {
s, err := Parse(goodMsg)

assert.NoError(t, err, "Unexpected error parsing good sentence")
assert.Equal(t, PrefixGLGSV, s.GetSentence().Type, "Prefix does not match")
assert.Equal(t, PrefixGLGSV, s.Prefix(), "Prefix does not match")

sentence := s.(GLGSV)
assert.Equal(t, int64(3), sentence.TotalMessages, "Total messages does not match")
Expand All @@ -71,13 +71,13 @@ func TestGLGSVBadSentence(t *testing.T) {
Input string
Error string
}{
{"$GLGSV,3,1,11.2,03,03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*77", "GLGSV decode number of SVs in view error: 11.2"},
{"$GLGSV,A3,1,11,03,03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "GLGSV decode total number of messages error: A3"},
{"$GLGSV,3,A1,11,03,03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "GLGSV decode message number error: A1"},
{"$GLGSV,3,1,11,A03,03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "GLGSV decode SV prn number error: A03"},
{"$GLGSV,3,1,11,03,A03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "GLGSV decode elevation error: A03"},
{"$GLGSV,3,1,11,03,03,A111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "GLGSV decode azimuth error: A111"},
{"$GLGSV,3,1,11,03,03,111,A00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "GLGSV decode SNR error: A00"},
{"$GLGSV,3,1,11.2,03,03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*77", "nmea: GLGSV invalid number of SVs in view: 11.2"},
{"$GLGSV,A3,1,11,03,03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "nmea: GLGSV invalid total number of messages: A3"},
{"$GLGSV,3,A1,11,03,03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "nmea: GLGSV invalid message number: A1"},
{"$GLGSV,3,1,11,A03,03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "nmea: GLGSV invalid SV prn number: A03"},
{"$GLGSV,3,1,11,03,A03,111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "nmea: GLGSV invalid elevation: A03"},
{"$GLGSV,3,1,11,03,03,A111,00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "nmea: GLGSV invalid azimuth: A111"},
{"$GLGSV,3,1,11,03,03,111,A00,04,15,270,00,06,01,010,12,13,06,292,00*2A", "nmea: GLGSV invalid SNR: A00"},
}
for _, tc := range tests {
_, err := Parse(tc.Input)
Expand All @@ -89,10 +89,8 @@ func TestGLGSVBadSentence(t *testing.T) {

func TestGLGSVWrongSentence(t *testing.T) {
wrongMsg := "$GPXTE,A,A,4.07,L,N*6D"
sent := Sentence{}
sent.parse(wrongMsg)
msg := GLGSV{Sentence: sent}
err := msg.parse()
sent, _ := ParseSentence(wrongMsg)
_, err := NewGLGSV(sent)
assert.Error(t, err, "Parse error not returned")
assert.Equal(t, "GPXTE is not a GLGSV", err.Error(), "Incorrect error message")
assert.Equal(t, "nmea: GLGSV invalid prefix: GPXTE", err.Error(), "Incorrect error message")
}
87 changes: 28 additions & 59 deletions gngga.go
Original file line number Diff line number Diff line change
@@ -1,70 +1,39 @@
package nmea

import "fmt"

const (
// PrefixGNGGA prefix
PrefixGNGGA = "GNGGA"
)

// GNGGA is the Time, position, and fix related data of the receiver.
type GNGGA struct {
Sentence
// Time of fix.
Time string
// Latitude.
Latitude LatLong
// Longitude.
Longitude LatLong
// Quality of fix.
FixQuality string
// Number of satellites in use.
NumSatellites string
// Horizontal dilution of precision.
HDOP string
// Altitude.
Altitude string
// Geoidal separation
Separation string
// Age of differential GPD data.
DGPSAge string
// DGPS reference station ID.
DGPSId string
}

func NewGNGGA(sentence Sentence) GNGGA {
s := new(GNGGA)
s.Sentence = sentence
return *s
Sent
Time Time // Time of fix.
Latitude LatLong // Latitude.
Longitude LatLong // Longitude.
FixQuality string // Quality of fix.
NumSatellites int64 // Number of satellites in use.
HDOP float64 // Horizontal dilution of precision.
Altitude float64 // Altitude.
Separation float64 // Geoidal separation
DGPSAge string // Age of differential GPD data.
DGPSId string // DGPS reference station ID.
}

func (s GNGGA) GetSentence() Sentence {
return s.Sentence
}

func (s *GNGGA) parse() error {
var err error

if s.Type != PrefixGNGGA {
return fmt.Errorf("%s is not a %s", s.Type, PrefixGNGGA)
}
s.Time = s.Fields[0]
s.Latitude, err = NewLatLong(fmt.Sprintf("%s %s", s.Fields[1], s.Fields[2]))
if err != nil {
return fmt.Errorf("GNGGA decode error: %s", err)
}
s.Longitude, err = NewLatLong(fmt.Sprintf("%s %s", s.Fields[3], s.Fields[4]))
if err != nil {
return fmt.Errorf("GNGGA decode error: %s", err)
}
s.FixQuality = s.Fields[5]
if s.FixQuality != Invalid && s.FixQuality != GPS && s.FixQuality != DGPS {
return fmt.Errorf("Invalid fix quality [%s]", s.FixQuality)
}
s.NumSatellites = s.Fields[6]
s.HDOP = s.Fields[7]
s.Altitude = s.Fields[8]
s.Separation = s.Fields[10]
s.DGPSAge = s.Fields[12]
s.DGPSId = s.Fields[13]
return nil
// NewGNGGA constructor
func NewGNGGA(s Sent) (GNGGA, error) {
p := newParser(s, PrefixGNGGA)
return GNGGA{
Sent: s,
Time: p.Time(0, "time"),
Latitude: p.LatLong(1, 2, "latitude"),
Longitude: p.LatLong(3, 4, "longitude"),
FixQuality: p.EnumString(5, "fix quality", Invalid, GPS, DGPS),
NumSatellites: p.Int64(6, "number of satelites"),
HDOP: p.Float64(7, "hdop"),
Altitude: p.Float64(8, "altitude"),
Separation: p.Float64(10, "separation"),
DGPSAge: p.String(12, "dgps age"),
DGPSId: p.String(13, "dgps id"),
}, p.Err()
}
24 changes: 12 additions & 12 deletions gngga_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@ func TestGNGGAGoodSentence(t *testing.T) {

assert.NoError(t, err, "Unexpected error parsing good sentence")

lat, _ := NewLatLong("6325.6138 N")
lon, _ := NewLatLong("01021.4290 E")
lat, _ := ParseLatLong("6325.6138 N")
lon, _ := ParseLatLong("01021.4290 E")
// Attributes of the parsed sentence, and their expected values.
expected := GNGGA{
Sentence: Sentence{
Sent: Sent{
Type: "GNGGA",
Fields: []string{"203415.000", "6325.6138", "N", "01021.4290", "E", "1", "8", "2.42", "72.5", "M", "41.5", "M", "", ""},
Checksum: "7C",
Raw: "$GNGGA,203415.000,6325.6138,N,01021.4290,E,1,8,2.42,72.5,M,41.5,M,,*7C",
},
Time: "203415.000",
Time: Time{true, 20, 34, 15, 0},
Latitude: lat,
Longitude: lon,
FixQuality: GPS,
NumSatellites: "8",
HDOP: "2.42",
Altitude: "72.5",
Separation: "41.5",
NumSatellites: 8,
HDOP: 2.42,
Altitude: 72.5,
Separation: 41.5,
DGPSAge: "",
DGPSId: "",
}
Expand All @@ -42,23 +42,23 @@ func TestGNGGABadType(t *testing.T) {
s, err := Parse(badType)

assert.NoError(t, err, "Unexpected error parsing sentence")
assert.NotEqual(t, "GNGGA", s.GetSentence().Type, "Unexpected sentence type")
assert.NotEqual(t, "GNGGA", s.Prefix(), "Unexpected sentence type")
}

func TestGNGGABadLatitude(t *testing.T) {
badLat := "$GNGGA,034225.077,A,S,15124.5567,E,1,03,9.7,-25.0,M,21.0,M,,0000*24"
_, err := Parse(badLat)

assert.Error(t, err, "Parse error not returned")
assert.Equal(t, "GNGGA decode error: cannot parse [A S], unknown format", err.Error(), "Error message does not match")
assert.Equal(t, "nmea: GNGGA invalid latitude: cannot parse [A S], unknown format", err.Error(), "Error message does not match")
}

func TestGNGGABadLongitude(t *testing.T) {
badLon := "$GNGGA,034225.077,3356.4650,S,A,E,1,03,9.7,-25.0,M,21.0,M,,0000*12"
_, err := Parse(badLon)

assert.Error(t, err, "Parse error not returned")
assert.Equal(t, "GNGGA decode error: cannot parse [A E], unknown format", err.Error(), "Error message does not match")
assert.Equal(t, "nmea: GNGGA invalid longitude: cannot parse [A E], unknown format", err.Error(), "Error message does not match")
}

func TestGNGGABadFixQuality(t *testing.T) {
Expand All @@ -67,5 +67,5 @@ func TestGNGGABadFixQuality(t *testing.T) {
_, err := Parse(badMode)

assert.Error(t, err, "Parse error not returned")
assert.Equal(t, err.Error(), "Invalid fix quality [5]", "Error message not as expected")
assert.Equal(t, err.Error(), "nmea: GNGGA invalid fix quality: 5", "Error message not as expected")
}
Loading

0 comments on commit 9fb5bf4

Please sign in to comment.