adrianmo / go-nmea Goto Github PK
View Code? Open in Web Editor NEWA NMEA parser library in pure Go
License: MIT License
A NMEA parser library in pure Go
License: MIT License
I could not find an example for processing AIS 5 message here. This type of message has more than one line for example:
\g:1-2-3730,s:43576,c:1654340281,t:165434038119!AIVDM,2,1,7,,569EH`8000009aGUB20IF1UD4r1UF3OK7>22220N4PT38t0000000000,042
\g:2-2-37305A!AIVDM,2,2,7,,000000000000000,262
Is there any way to process such cases?
Update .travis.yml
to automate testing of the library on Golang 1.8, 1.9, and 1.10.
I have the following sentence:
$GPRMC,142754.0,A,4302.539570,N,07920.379823,W,0.0,,070617,0.0,E,A*3F
Which fails to parse with: GPRMC decode course error:
due to the parser not handling null fields correctly. The easiest solution would be to use 0
when there's a null field, but idk if that's a good idea.
https://www.trimble.com/OEM_ReceiverHelp/V4.44/en/NMEA-0183messages_MessageOverview.html
All messages conform to the NMEA-0183 version 3.01 format. All begin with $ and end with a carriage return and a line feed. Data fields follow comma (,) delimiters and are variable in length. Null fields still follow comma (,) delimiters, but contain no information.
When a value is missing in a nmea string the float or int value in the parsed sentence is set to 0. This way it is hard to determine if the value is really 0 or the data was missing. E.g. $GPVTG,0.3,T,,M,,N,12.6,K*78
would result in GroundSpeedKnots: 0
and GroundSpeedKPH: 12.6
. Now it is easy to guess that that GroundSpeedKnots
is invalid, but for TrueTrack: 0.3
and MagneticTrack: 0
it is not possible.
Is there a specific reason why this is done in this way?
I would suggest to add getters to the sentences for all the value like:
func (s VTG) GetTrueTrack() (float64, error) {
if s.hasValidTrueTrack {
return s.TrueTrack, nil
}
return 0, fmt.Errorf("TrueTrack is missing in the nmea string")
}
These getters can check an internal state for each value and return an error if the value was not available in the original nmea string. This will also not break existing code because it is still possible to use TrueTrack
, MagneticTrack
etc directly.
if checksum != strings.TrimSpace(checksumRaw) {
return BaseSentence{}, fmt.Errorf(
"nmea: sentence checksum mismatch [%s != %s]", checksum, checksumRaw)
}
Update the example to show how to access sentence fields.
E.g.:
package main
import (
"fmt"
"github.com/adrianmo/go-nmea"
)
func main() {
sentence := "$GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70"
m, err := nmea.Parse(sentence)
if err == nil {
s := m.(nmea.GPRMC)
fmt.Printf("Raw sentence: %v\n", s)
fmt.Printf("Time: %v\n", s.Time.String())
fmt.Printf("Validity: %v\n", s.Validity)
fmt.Printf("Latitude GPS: %v\n", s.Latitude.PrintGPS())
fmt.Printf("Latitude DMS: %v\n", s.Latitude.PrintDMS())
fmt.Printf("Longitude GPS: %v\n", s.Longitude.PrintGPS())
fmt.Printf("Longitude DMS: %v\n", s.Longitude.PrintDMS())
fmt.Printf("Speed: %v\n", s.Speed)
fmt.Printf("Course: %v\n", s.Course)
fmt.Printf("Date: %v\n", s.Date.String())
fmt.Printf("Variation: %v\n", s.Variation)
} else {
panic(err)
}
}
Output:
$ go run main/main.go
Raw sentence: $GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70
Time: 22:05:16.0000
Validity: A
Latitude GPS: 5133.8200
Latitude DMS: 51° 33' 49.200000"
Longitude GPS: 042.2400
Longitude DMS: 0° 42' 14.400000"
Speed: 173.8
Course: 231.8
Date: 13/06/94
Variation: -4.2
I am creating application to read nmea values and send them to NATS message bus and I one feature that I have is that user can provide configuration (file) that has list of sentences and fields that should filter out of stream of NMEA messages it receives.
For example - we have GPS, Echosounder, Wind sensor all multiplexed into NMEA0183 bus we read. Sometimes we only want to filter GPS RMC messages but sometimes we want other hardware messages also. As this library evolves more and more supported sentences will be added. For each of those messages we would need to create if/switch to be able to read it - pack all fields of message into custom struct we have. We can not just marshall current nmea.Sentence
as our schema is different from what marshalling nmea.Sentence creates.
So it would be nice if there would be way to get list of field names that sentence has and then we can pair them with nmea.BaseSentence.Fields
slice values to our own schema.
Maybe that context
argument that is used when adding field to sentence, could be stored and exposed as public slice
Line 34 in a4c9590
or there would be some method on Sentence what would return list/map of fieldname+fieldvalue (ala map[string]interface{}
) so you could "dynamically" get all fields and filter what you need.
About errors. When parsing fails currently only first error is stored and all subsequent errors are discarded. I propose if p.EnumString
and other parsing method errors would be distinguishable from each other and parsers would store all errors. it would allow you to introspect what went wrong and some circumstances ignore some error types and still use the parsed sentence.
maybe just wrapping them (or storing into slice or multierror)
func (p *Parser) SetErr(context, value string) {
if p.err == nil {
p.err = fmt.Errorf("nmea: %s invalid %s: %s", p.Prefix(), context, value)
} else {
p.err = fmt.Errorf("nmea: %s invalid %s: %s, err: %w", p.Prefix(), context, value, p.err)
}
}
Hi, i am newbie on Golang and the NMEA library too.
I have a question about the output when i use nmea.ParseSentence.
this is the code, i changed nmea.Parse to nmea.ParseSentence
package main
import (
"fmt"
"github.com/adrianmo/go-nmea"
)
func main() {
m, err := nmea.ParseSentence("$GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70")
if err == nil {
fmt.Printf("%+v\n", m)
}
}
but the output still same with nmea.Parse. The output:
$GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70
is it the right output?
I want to parse that NMEA, so i choose the ParseSentence.
Thanks for your help
Version 2.x should take into account that geographical coordinate parsing must always be done in the context of the direction. Latitude and longitude have different ranges. In addition, currently only the Decimal format stores information about the direction of a given coordinate (positive / negative values). Parsing data in other formats loses direction information.
Since there's no public canonical nmea reference, we've been linking to different resources on the web. It would be better to maintain our own copy of the message specifications that we implement.
I want to replace testify with gotesttools. It uses google/go-cmp instead of reflect.DeepEqual which lets you override the comparison function for specific types. This will allow us to have a single test helper for comparing message types instead of rolling separate ones. It also outputs nicer diffs.
occur error when parsing data.
i received error message, "nmea: IIXDR invalid transducer type: A"
my gps data sender is providing bellow data
$IIXDR, A, 0.0, D, ROLL, A, 0.0, D, PITCH*15
As of version 1.5.0 and higher, I get the following when parsing data from my boat:
$YDRMC,050700.00,A,5524.8683,N,01255.7938,E,0.2,181.3,230623,4.3,E,A,C*5F
nmea: YDRMC invalid navigation status: C
I am running your example code on GNRMC data received from my GNSS module.
On nmea.Parse(sentence) I get:
]019/06/17 21:26:23 Couldn't parse GPS data: nmea: sentence checksum mismatch [79 != 79
2019/06/17 21:26:24 $GNRMC,192624.000,A,5327.813301,N,01432.630601,E,0.00,325.41,170619,,,A*7E
]019/06/17 21:26:24 Couldn't parse GPS data: nmea: sentence checksum mismatch [7E != 7E
2019/06/17 21:26:25 $GNRMC,192625.000,A,5327.813301,N,01432.630601,E,0.00,325.41,170619,,,A*7F
]019/06/17 21:26:25 Couldn't parse GPS data: nmea: sentence checksum mismatch [7F != 7F
^C2019/06/17 21:26:25 main: Got signal: interrupt
2019/06/17 21:26:26 $GNRMC,192626.000,A,5327.813301,N,01432.630601,E,0.00,325.41,170619,,,A*7C
]019/06/17 21:26:26 Couldn't parse GPS data: nmea: sentence checksum mismatch [7C != 7C
^C2019/06/17 21:26:27 $GNRMC,192627.000,A,5327.813301,N,01432.630601,E,0.00,325.41,170619,,,A*7D
]019/06/17 21:26:27 Couldn't parse GPS data: nmea: sentence checksum mismatch [7D != 7D
Both checksums seem the same to me in the output above.
The place I pasted your example code:
DPT documentation refers to https://gpsd.gitlab.io/gpsd/NMEA.html#_dpt_depth_of_water and in that is example $INDPT,2.3,0.0*46
that example is not parseable by the library. I get nmea: INDPT invalid range scale: index out of range
Some other documents ala https://www.tronico.fi/OH6NT/docs/NMEA0183.pdf
describe DPT as
or https://www.eye4software.com/hydromagic/documentation/nmea0183/ as Example: $SDDPT,3.6,0.0*52
It would be nice if DTP parsing can handle 2 and 3 fields gracefully without erroring.
Older devices sometimes do not implement NMEA0183 correctly by omitting CRC. It would be nice if there would be way to make parser ignore CRC mismatches for certain sentences.
We are retrofitting 2005 built vessel that has GPS device sending sentences without CRC. Our navigation engineers say it is not very rare to have older devices like that. So for example devices reading/receiving NMEA0183 sentences have sometimes option to disable CRC checks because of this sad reality.
I think MTK implementation is not correct. MTK is command protocol embedded into NMEA sentence. Fields that current MTK struct has are meant for MTK packet "PMTK001" but actually MTK packet can have variable amound of data fields.
See:
When I am trying to parse the serial output of an u-blox USB GPS Interface, I get the following message, along other checksum warnings.
2018/07/17 11:24:37 $GPRMC,092441.00,V,,,,,,,170718,,,N*7F
panic: interface conversion: nmea.Sentence is nmea.GPVTG, not nmea.GPRMC
--
2018/07/17 11:25:42 $GPRMC,092546.00,V,,,,,,,170718,,,N*79
]018/07/17 11:25:42 nmea: sentence checksum mismatch [79 != 79
--
2018/07/17 11:59:10 NMEA RAW is: '$GPVTG,,,,,,,,,N*30'
panic: interface conversion: nmea.Sentence is nmea.GPVTG, not nmea.GPRMC
I would like to extend this lib to support custom message parsing, is this something you would consider merging. We are using this to parse some custom message which are not part of the NMEA standard. The idea is to have a way to register parsers for new message types.
Even though I am using the latest version (v1.5.0) but I cant use the new added supported sentences such as alarm sentences.
The LonDir function seems to be incorrect. Longitude greater than 0 should be East, but this function returns West.
I think the API is in a good place right now and we should tag a 1.0 release. No more breaking changes after that.
On this string:
$GNRMC,100538.00,A,5546.27711,N,03736.91144,E,0.061,,260318,,,A*60
Before lib update to 22095aa - all worked.
The NMEA 0183 protocol offers multiple talkers based on which equipment generated the message.
GP indicates a GPS receiver, GL a GLONASS receiver, GN a combined GNSS receiver, IN an integrated navigation receiver and so forth. See here for examples of different talkers.
As of today, go-nmea only accepts GP for most messages as talker. Is there an easy way of allowing different talkers for all NMEA messages, or is it necessary to implement specific functions for all talkers?
A concrete example is the HDT, which in many cases is HEHDT and INHDT.
An easy (but dirty) way is of course to manipulate the talker into GP.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.