go-nmea

repository·master·Indexed 42 days ago

https://github.com/adrianmo/go-nmea

A Go library for parsing NMEA 0183 sentences, featuring support for NMEA 4.10 TAG Blocks and the ability to register custom parsers for proprietary or unsupported sentence types. It provides built-in support for various standard and proprietary sentences (e.g., GGA, GLL, RMC, VTG, AAM, ABM, ACK, ACN, ALA, ALC, ALF, ALR) based on the IEC 61162-1:2016 standard.

Tokens
43.4K
Snippets
160
Records
196
Agent score
54%

What's inside go-nmea

  1. Overview of go-nmea features

    master

    The go-nmea library provides several capabilities for handling NMEA 0183 data in Go:

    • Parsing: Parse individual NMEA 0183 sentences.
    • NMEA 4.10 Support: Support for sentences containing NMEA 4.10 "TAG Blocks".
    • Extensibility: Ability to register custom parsers for sentence types that are not supported out-of-the-box.
  2. Handle optional values with Null types

    master

    By default, omitted numeric values in NMEA sentences are parsed as 0. To distinguish between a literal 0 and a missing/undefined value, use nmea.Int64 and nmea.Float64 types in your custom message structs instead of standard int64 or float64.

    When parsing, use the corresponding methods on the parser:

    • (*Parser).NullInt64(index, name)
    • (*Parser).NullFloat64(index, name)

    Both nmea.Int64 and nmea.Float64 contain a Value field and a Valid boolean field. Valid is true if the field was present in the sentence, and false otherwise.

    type VTG struct {
    	nmea.BaseSentence
    	TrueTrack        nmea.Float64
    	MagneticTrack    nmea.Float64
    	GroundSpeedKnots nmea.Float64
    	GroundSpeedKPH   nmea.Float64
    }
    
    // Inside RegisterParser callback:
    p := nmea.NewParser(s)
    return VTG{
    	BaseSentence:     s,
    	TrueTrack:        p.NullFloat64(0, "true track"),
    	MagneticTrack:    p.NullFloat64(2, "magnetic track"),
    	GroundSpeedKnots: p.NullFloat64(4, "ground speed (knots)"),
    	GroundSpeedKPH:   p.NullFloat64(6, "ground speed (km/h)"),
    }, p.Err()
  3. Access NMEA 4.10 TAG Block values

    master

    NMEA 4.10 TAG blocks (e.g., \s:Source,c:Value*CRC\!) can be accessed through the TagBlock field on the parsed message struct. The TagBlock struct provides access to the Time (Unix timestamp) and Source of the block.

    // Assuming 's' is a parsed sentence like VDMVDO
    parsed := s.(nmea.VDMVDO)
    fmt.Printf("TAG Block timestamp: %v\n", time.Unix(parsed.TagBlock.Time, 0))
    fmt.Printf("TAG Block source:    %v\n", parsed.TagBlock.Source)
  4. Implement and register a custom message parser

    master
    If you need to parse a message containing an unsupported sentence type, you can implement and register your own message parser. This allows you to extend the library's capabilities immediately. Refer to the #custom-message-parsing section in the documentation for implementation details.
  5. Interpret GNSSQuality and IMUAlignmentStatus in PASHR sentences

    master

    The meaning of GNSSQuality and IMUAlignmentStatus in a PASHR sentence varies depending on the hardware manufacturer (e.g., Trimble vs. Novatel).

    GNSSQuality

    ValueTrimble MeaningNovatel Meaning
    0Fix not availableNo position
    1GNSS mode, fix validAll non-RTK fixed integer positions
    2Differential GPSRTK fixed integer position
    3GNSS PPS mode-
    4Fixed RTK mode-
    5Float RTK mode-
    6DR mode-

    IMUAlignmentStatus

    ValueTrimble MeaningNovatel Meaning
    0GPS OnlyAll SPAN Pre-Alignment INS Status
    1Coarse LevelingAll SPAN Post-Alignment INS Status (includes INS_ALIGNMENT_COMPLETE, INS_SOLUTION_GOOD, etc.)
    2Degraded Solution-
    3Aligned-
    4Full Navigation Mode-
  6. Parse built-in NMEA messages

    master

    Use nmea.Parse(sentence) to parse standard NMEA sentences. The function returns a nmea.Sentence interface. To access specific fields, check the sentence type using s.DataType() and then perform a type assertion to the corresponding message struct (e.g., nmea.RMC).

    For coordinate formatting, use nmea.FormatGPS(value) for decimal degrees and nmea.FormatDMS(value) for Degrees, Minutes, Seconds format.

    package main
    
    import (
    	"fmt"
    	"log"
    	"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"
    	s, err := nmea.Parse(sentence)
    	if err != nil {
    		log.Fatal(err)
    	}
    	if s.DataType() == nmea.TypeRMC {
    		m := s.(nmea.RMC)
    		fmt.Printf("Time: %s\n", m.Time)
    		fmt.Printf("Latitude GPS: %s\n", nmea.FormatGPS(m.Latitude))
    		fmt.Printf("Latitude DMS: %s\n", nmea.FormatDMS(m.Latitude))
    	}
    }
  7. Register custom message parsers

    master

    To support non-standard or proprietary NMEA sentences, use nmea.RegisterParser(type, callback) or nmea.MustRegisterParser(type, callback).

    1. Define a struct that embeds nmea.BaseSentence to hold the parsed data.
    2. In the callback, use nmea.NewParser(s) to create a helper for extracting fields.
    3. Use helper methods like .Time(), .String(), .Int64(), or .Float64() to populate your struct.
    4. Return the populated struct and any errors from p.Err().
    type XYZType struct {
    	nmea.BaseSentence
    	Time    nmea.Time
    	Counter int64
    	Label   string
    	Value   float64
    }
    
    err := nmea.RegisterParser("XYZ", func(s nmea.BaseSentence) (nmea.Sentence, error) {
    	p := nmea.NewParser(s)
    	return XYZType{
    		BaseSentence: s,
    		Time:         p.Time(0, "time"),
    		Label:        p.String(1, "label"),
    		Counter:      p.Int64(2, "counter"),
    		Value:        p.Float64(3, "value"),
    	}, p.Err()
    })
  8. Customize the sentence parser

    master

    You can override the default parsing behavior by creating an instance of nmea.SentenceParser. This allows you to provide custom logic for prefix matching, CRC checking, or handling tag blocks via the following fields:

    • CustomParsers: A map of custom parser implementations.
    • ParsePrefix: Custom logic for identifying sentence prefixes.
    • CheckCRC: Custom CRC validation logic.
    • OnTagBlock: Callback for handling NMEA 4.10 TAG blocks.
    p := nmea.SentenceParser{
        CustomParsers: nil,
        ParsePrefix:   nil,
        CheckCRC:      nil,
        OnTagBlock:    nil,
    }
    s, err := p.Parse("$GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70")
  9. View supported NMEA0183 sentences

    master

    The go-nmea library supports a wide range of NMEA0183 sentences based on the IEC 61162-1:2016 standard, including standard sentences (e.g., GGA, GLL, RMC, VTG) and various proprietary sentences (e.g., PASHR, PGRME, PMTK001).

    If you encounter an unsupported sentence type, you can implement and register a custom message parser to unblock your development. If your custom parser is useful, you are encouraged to contribute it back to the library via a Pull Request.

    ### Supported sentences
    
    | Sentence           | Description                                                         | References                                                                                     |
    |--------------------|---------------------------------------------------------------------|------------------------------------------------------------------------------------------------|
    | [AAM](./aam.go)    | Waypoint arrival alarm                                              | [gpsd](https://gpsd.gitlab.io/gpsd/NMEA.html#_aam_waypoint_arrival_alarm)                      |
    | ABK                | AIS addressed and binary broadcast acknowledgement                  |                                                                                                |
    | [ABM](./abm.go)    | AIS addressed binary and safety related message                     |                                                                                                |
    | ACA                | AIS channel assignment message                                      |                                                                                                |
    | [ACK](./ack.go)    | Acknowledge alarm                                                    |                                                                                                |
    | [ACN](./acn.go)    | Alert command                                                       |                                                                                                |
    | ACS                | AIS channel management information source                           |                                                                                                |
    | AIR                | AIS interrogation request                                           |                                                                                                |
    | AKD                | Acknowledge detail alarm condition                                  |                                                                                                |
    | [ALA](./ala.go)    | Report detailed alarm condition                                     |                                                                                                |
    | [ALC](./alc.go)    | Cyclic alert list                                                   |                                                                                                |
    | [ALF](./alf.go)    | Alert sentence                                                      |                                                                                                |
    | [ALR](./alr.go)    | Set alarm state                                                      |                                                                                                |
    | [APB](./apb.go)    | Heading/track controller (autopilot) sentence B                     | [gpsd](https://gpsd.gitlab.io/gpsd/NMEA.html#_apb_autopilot_sentence_b)                        |
    | [ARC](./arc.go)    | Alert command refused                                               |                                                                                                |
    | [BBM](./bbm.go)    | AIS broadcast binary message                                        |                                                                                                |
    | [BEC](./bec.go)    | Bearing and distance to waypoint, Dead reckoning                    | [1](http://www.nmea.de/nmea0183datensaetze.html#bec)                                           |
    | [BOD](./bod.go)    | Bearing origin to destination                                       | [gpsd](https://gpsd.gitlab.io/gpsd/NMEA.html#_bod_bearing_waypoint_to_waypoint)                |
    | [BWC](./bwc.go)    | Bearing and distance to waypoint, Great circle                      | [gpsd](https://gpsd.gitlab.io/gpsd/NMEA.html#_bwc_bearing_distance_to_waypoint_great_circle) |
  10. Handle unsupported NMEA sentences

    master

    When the parser encounters a sentence prefix it does not recognize, it returns a NotSupportedError.

    You can check for this error to identify when your application is receiving unknown NMEA data types.

    NotSupportedError contains a Prefix field indicating the unsupported string.