Documentation ¶
Overview ¶
Package nmeais is a library for quickly parsing AIS messages from network packets, and merging streams from multiple sources.
Index ¶
Constants ¶
const ( ChecksumPassed = ChecksumResult('t') // The sentence has a chacksum that matches ChecksumFailed = ChecksumResult('f') // The sentence has a checksum that doesn't match ChecksumAbsent = ChecksumResult('N') // The sentence has no checksum )
The three valid values of ChecksumResult
Variables ¶
This section is empty.
Functions ¶
func FirstSentenceInBuffer ¶
FirstSentenceInBuffer extracts the text of what looks like the first AIS NMEA0183 sentence in an (IO) buffer. `next` is the index of the first byte that wasn't copied, it is len(bufferSlice) if the entire input was used. Otherwise it's ensured that `copiedSentence“ ends with a "\r\n" line delimiter. Bytes before the first '!' are considered noise and skipped. This newline fixing and '!'-seeking means that `next` might be different from len(copiedSentence)-len(incomplete). The sentence is always copied so that the input buffer can be reused immediately. If the buffer doesn't contain a complete sentence, a copy of the input is returned as `copiedSentence` and `next` is -1. If the buffer doesn't even contain the start of a sentence, `"",-1` is returned to not create an edge case where `used` is positive but `copiedSentence` is empty. `incomplete` is a receptacle for that copy: if it's non-empty it's prepended to `copiedSentence` and the search for a starting '!' is dropped.
Types ¶
type ChecksumResult ¶
type ChecksumResult byte
ChecksumResult says whether a sentence has a checksum and if it matches
type DuplicateTester ¶
type DuplicateTester struct {
// contains filtered or unexported fields
}
DuplicateTester is a tool for filtering out messages received from multiple AIS ssources. It does this by comparing new message against all recently checked messages. This means identical messages from the same source will also be filtered. What's considered recent is controlled by a parmater to the constructor, and a package might be comparaed against all received within the double of that. It uses internal locking, which makes it safe to share instances between goroutines.
func NewDuplicateTester ¶
func NewDuplicateTester(minKeepAlive time.Duration) *DuplicateTester
NewDuplicateTester creates a new DuplicateTester and starts a goroutine that periodically removes old messages.
input:
minKeepAlive - How long the messages should at least be kept in the map E.g. 5 seconds -> a new message is tested for duplicates among all the messages recieved within the last 5 to 10 seconds
func (*DuplicateTester) Close ¶
func (dt *DuplicateTester) Close()
Close tells the internal goroutine to stop.
func (*DuplicateTester) IsDuplicate ¶
func (dt *DuplicateTester) IsDuplicate(msg *Message) bool
IsDuplicate compares msg against all messages passed to IsDuplicate within the last 1x to 20 minKeepAlive.
Input: msg - Only the raw text of the first sentence is used. (for speed and simplicity) Output: exists - true if the message is previously known
- false if the message is new
type Message ¶
type Message struct { SourceName string // alias of the AIS listener the message came from // contains filtered or unexported fields }
Message is an AIS message stored as decoded NMEA 0183 sentences. It also stores the alias of the source it came from and the time the last part was received.
func (*Message) ArmoredPayload ¶
ArmoredPayload joins together the payload part of the sentences the message was parsed from.
func (*Message) DearmoredPayload ¶
DearmoredPayload undoes the siz-bit ASCII encoding of the payload. This function is completely untested.
func (*Message) Sentences ¶
Sentences returns a slice containing the sentences the message is made up of.
type MessageAssembler ¶
type MessageAssembler struct { MaxMessageTimespan time.Duration MaxSentencesBetween uint64 SourceName string // contains filtered or unexported fields }
MessageAssembler takes in sentences out of order and returns a Message if the sentence completes one. Sentences can come out of order, as can messages with different SMID. Single-sentence messages pass through without affecting multi-sentence messages.
func NewMessageAssembler ¶
func NewMessageAssembler(maxSentencesBetween uint, maxMessageTimespan time.Duration, sourceName string) MessageAssembler
NewMessageAssembler creates a new MessageAssembler. There's nothing happening behind the scenes, so a value is returned, but the struct is quite big so it shouldn't be moved around too much.
- maxSentencesBetwee: The maximum number of sentences that might be received between
two of the same message. Scales with traffic and the number of sentences in a message.
- maxMessageTimespan: The maximum duration between when the first and last sentence
of a message was received. Doesn't scale with traffic or the number of sentences in a message, but becomes relevant if the connection goes down or traffic slows to a crawl.
func (*MessageAssembler) Accept ¶
func (ma *MessageAssembler) Accept(s Sentence) (*Message, error)
Accept takes in a sentence, returns a Message if it completes one, an error if it's invalid or aborts an incomplete one, or neither. Sentences that have failed the checksum are checked against incomplete messages, and if it matches the message is aborted.
type Sentence ¶
type Sentence struct { Identifier [5]byte // "AIVDM" and the like Parts uint8 // starts at 1 PartIndex uint8 // starts at 0 SMID uint8 // Sequential message ID, 10 when missing (10 makes indexing based on it easy) HasSMID bool // Is false if SMID field is empty Channel byte // '*' if empty Checksum ChecksumResult Received time.Time Text string // everything plus "\r\n" // contains filtered or unexported fields }
Sentence contains the values parsed from a NMEA 0183 sentence assumed to encapsulate an AIS message, and the sentence itself. Saves all possibly interesting information; some of them are never actually used for anything. There are many fields, but most of them are small: Text takes up nearly half the size.
func ParseSentence ¶
ParseSentence extracts the fields out of an assumed NMEA0183 AIS-containing sentence. It does the minimum possible validation for the sentence to be useful: All fields (except Received) might contain invalid values, call .Validate() to check them. The checksum is evaluated if present, but not even a checksum mismatch is an error; the result is stored in .Checksum. For speed, ParseSentence assumes the correct width of fixed-width fields.