aislib

package module
v0.0.0-...-3a9a588 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2019 License: GPL-3.0 Imports: 7 Imported by: 26

README

aislib

A Go library to read AIS sentences and decode AIS messages.

The most simple example of decoding and printing an AIS message:

$ cd examples/example
$ echo '!AIVDM,1,1,,A,14eGrSPP00ncMJTO5C6aBwvP2D0?,0*7A' | go run example.go
=== Class A Position Report (1) ===
 Repeat       : 0
 MMSI         : 316013198 [Ship, Canada]
 Nav.Status   : Under way using engine
 Turn (ROT)   : no turn information
 Speed (SOG)  : 0.0 knots
 Accuracy     : High accuracy (<10m)
 Coordinates  : 130°18.9742'W  54°19.2666N
 Course (COG) : 237.9°
 Heading (HDG): not available
 Manuever ind.: not available
 RAIM         : in use

History

While I was working for marine.travel —a social site for sea lovers— I wanted to polish my Go skills. I thought a nice project would be an AIS parser, which later we could use to implement new functionality for our product.

I wrote aislib outside my work duties and time, but intended to use it there. Unfortunately marine.travel didn't make it. Thankfully we are on new, equally exciting adventures now. Since aislib didn't have any prospects anymore, I asked for permission to release my code under a permissive license. It was granted and here is the repository. :)

Quality and Use Disclaimer

Please bare in mind that this was my first big-ish project in golang, some poor choices are to be expected. I am pretty certain that the main functionality is robust though, so if it doesn't fit your needs, you could use the decoding parts and implement your ideal management parts.

Features and State

Inside the examples/ directory you will find two examples to get you going. Start with the simple one, example.go. To run:

 $ cat nmea-sample.txt | go run example.go

aislib can decode type 1, 2, 3 (Class A Position Report), 4 (Base Station Report), 5 (Static Voyage Data), 18 (Class B Position Report) messages. It may also understand type 8 (binary Broadcast) messages, report their respective type and extract the binary payload.

These are the most common types you will find. If you are interested in extending aislib, it is worth implementing type 21 and 24 decoding.

A limitation is multi-sentence messages. Messages that span across AIS sentences will only be decoded if (a) they come in order and (b) do not interleave with other multi-sentence messages.

In my experience from capturing AIS data from ais1.shipraiser.net for many hours, the messages you receive almost always meet these criteria. I think I never saw a sentence parsing failing due to this restriction.

How it Works

As stated, some poor choices may have been made.

Each AIS message type has different fields. Thus I implement a router, that receives sentences, checks their type, their checksum and if the message they carry spans across many sentences (and it reconstructs the message's payload) and pass back the type and the payload. This work is done through channels, an incoming channel to the router, to pass AIS sentences and an outgoing channel to receive message payloads (and types). There is also a second outgoing channel where you receive the sentences that the router failed to recognize for any reason (e.g bad checksum or out of order multi-span message). It is useful for debugging.

So in sort you send AIS sentences into the router and get tuples with AIS message type and payload.

You should switch on the message type to the proper decoding function.

In retrospect, now I know that I could return just the message and let you use type assertion. This wouldn't change much though, as again you would need a select statement to deal with the result.

Check example.go to understand how the router and decoding function works.

License

Check LICENSE file. In sort it is GPL version 3 or greater.

Documentation

Overview

Package ais provides functions and types to work with AIS (Automatic Identification System) sentences (radio messages) and messages in AIVDM/AIVDO format.

An AIS sentence is one line, it is the actual radio message. An AIS message is the payload that is carried by one or more consecutive AIS sentences.

Index

Examples

Constants

This section is empty.

Variables

View Source
var BinaryBroadcastType = map[int]map[int]string{
	1: {
		11: "Meteorological/Hydrogological Data",
		13: "Fairway closed",
		15: "Extended ship and voyage",
		17: "VTS-Generated/Synthetic targets",
		19: "Marine traffic signals",
		21: "Weather observation from ship",
		22: "Area notice (broadcast)",
		24: "Extended ship and voyage",
		26: "Environmental",
		27: "Route info broadcast",
		29: "Text description broadcast",
		31: "Meteorological and Hydrological",
	},
	200: {
		10: "Ship static and voyage related data",
		23: "EMMA warning report",
		24: "Water levels",
		40: "Signal status",
	},
	316: {
		1:  "Weather Station or Wind or Water Level",
		2:  "Lockage Order or Estimated Lock Times",
		32: "Seaway Version Message",
	},
	366: {
		1:  "Weather Station or Wind or Water Level or PAWS Hydro / Current or PAWS Hydro / Salinity Temp or PAWS Vessel Procession Order",
		2:  "Lockage Order or Estimated Lock Times",
		32: "Seaway Version Message",
	},
}

Some Binary Broadcast types. The list isn't complete but I haven't searched for a better source

View Source
var EpfdFixTypes = [...]string{
	"Undefined", "GPS", "GLONASS", "Combined GPS/GLONASS", "Loran-C",
	"Chayka", "Integrated Navigation System", "Surveyed", "Galileo",
	"not defined", "not defined", "not defined", "not defined",
	"not defined", "not defined", "not defined",
}

EPFD Fix Codes

View Source
var Mid = map[int]string{}/* 288 elements not displayed */

Maritime Identification Digits, have a look at http://www.itu.int/online/mms/glad/cga_mids.sh?lang=en

View Source
var MmsiCodes = [...]string{
	"Ship", "Coastal Station", "Group of ships", "SAR —Search and Rescue Aircraft",
	"Diver's radio", "Aids to navigation", "Auxiliary craft associated with parent ship",
	"AIS SART —Search and Rescue Transmitter", "MOB —Man Overboard Device",
	"EPIRB —Emergency Position Indicating Radio Beacon", "Invalid MMSI",
}

Contains MMSI owners' descriptions. Currently not used anywhere

View Source
var NavigationStatusCodes = [...]string{
	"Under way using engine", "At anchor", "Not under command", "Restricted maneuverability",
	"Constrained by her draught", "Moored", "Aground", "Engaged in fishing", "Under way sailing",
	"status code reserved", "status code reserved", "status code reserved",
	"status code reserved", "status code reserved", "AIS-SART is active", "Not defined",
}

Navigation status codes

View Source
var ShipType = map[int]string{
	0:  "Not available",
	1:  "Reserved for future use",
	2:  "Reserved for future use",
	3:  "Reserved for future use",
	4:  "Reserved for future use",
	5:  "Reserved for future use",
	6:  "Reserved for future use",
	7:  "Reserved for future use",
	8:  "Reserved for future use",
	9:  "Reserved for future use",
	10: "Reserved for future use",
	11: "Reserved for future use",
	12: "Reserved for future use",
	13: "Reserved for future use",
	14: "Reserved for future use",
	15: "Reserved for future use",
	16: "Reserved for future use",
	17: "Reserved for future use",
	18: "Reserved for future use",
	19: "Reserved for future use",
	20: "Wing in ground (WIG)",
	21: "Wing in ground (WIG), Hazardous category A",
	22: "Wing in ground (WIG), Hazardous category B",
	23: "Wing in ground (WIG), Hazardous category C",
	24: "Wing in ground (WIG), Hazardous category D",
	25: "Wing in ground (WIG), Reserved for future use",
	26: "Wing in ground (WIG), Reserved for future use",
	27: "Wing in ground (WIG), Reserved for future use",
	28: "Wing in ground (WIG), Reserved for future use",
	29: "Wing in ground (WIG), Reserved for future use",
	30: "Fishing",
	31: "Towing",
	32: "Towing: length exceeds 200m or breadth exceeds 25m",
	33: "Dredging or underwater ops",
	34: "Diving ops",
	35: "Military ops",
	36: "Sailing",
	37: "Pleasure Craft",
	38: "Reserved",
	39: "Reserved",
	40: "High speed craft (HSC)",
	41: "High speed craft (HSC), Hazardous category A",
	42: "High speed craft (HSC), Hazardous category B",
	43: "High speed craft (HSC), Hazardous category C",
	44: "High speed craft (HSC), Hazardous category D",
	45: "High speed craft (HSC), Reserved for future use",
	46: "High speed craft (HSC), Reserved for future use",
	47: "High speed craft (HSC), Reserved for future use",
	48: "High speed craft (HSC), Reserved for future use",
	49: "High speed craft (HSC), No additional information",
	50: "Pilot Vessel",
	51: "Search and Rescue vessel",
	52: "Tug",
	53: "Port Tender",
	54: "Anti-pollution equipment",
	55: "Law Enforcement",
	56: "Spare - Local Vessel",
	57: "Spare - Local Vessel",
	58: "Medical Transport",
	59: "Noncombatant ship according to RR Resolution No. 18",
	60: "Passenger",
	61: "Passenger, Hazardous category A",
	62: "Passenger, Hazardous category B",
	63: "Passenger, Hazardous category C",
	64: "Passenger, Hazardous category D",
	65: "Passenger, Reserved for future use",
	66: "Passenger, Reserved for future use",
	67: "Passenger, Reserved for future use",
	68: "Passenger, Reserved for future use",
	69: "Passenger, No additional information",
	70: "Cargo",
	71: "Cargo, Hazardous category A",
	72: "Cargo, Hazardous category B",
	73: "Cargo, Hazardous category C",
	74: "Cargo, Hazardous category D",
	75: "Cargo, Reserved for future use",
	76: "Cargo, Reserved for future use",
	77: "Cargo, Reserved for future use",
	78: "Cargo, Reserved for future use",
	79: "Cargo, No additional information",
	80: "Tanker",
	81: "Tanker, Hazardous category A",
	82: "Tanker, Hazardous category B",
	83: "Tanker, Hazardous category C",
	84: "Tanker, Hazardous category D",
	85: "Tanker, Reserved for future use",
	86: "Tanker, Reserved for future use",
	87: "Tanker, Reserved for future use",
	88: "Tanker, Reserved for future use",
	89: "Tanker, No additional information",
	90: "Other Type",
	91: "Other Type, Hazardous category A",
	92: "Other Type, Hazardous category B",
	93: "Other Type, Hazardous category C",
	94: "Other Type, Hazardous category D",
	95: "Other Type, Reserved for future use",
	96: "Other Type, Reserved for future use",
	97: "Other Type, Reserved for future use",
	98: "Other Type, Reserved for future use",
	99: "Other Type, no additional information",
}

Ship types codes.

Functions

func CoordinatesDeg2Human

func CoordinatesDeg2Human(degLon, degLat float64) string

CoordinatesDeg2Human takes coordinates (lon, lat) in decimal degrees (DD), formats them as degrees minutes and returns them as string.

Example
fmt.Println(CoordinatesDeg2Human(-3.56725, 53.84251666666667))
Output:

3°34.0350'W  53°50.5510N

func CoordinatesMin2Deg

func CoordinatesMin2Deg(minLon, minLat float64) (float64, float64)

CoordinatesMin2Deg translates coordinates (lon, lat) in decimal minutes (×10^4) to decimal degrees. AIS data use decimal minutes but decimal degrees (DD) is a more universal format and easier to handle. Almost every third party asks for this format.

func DecodeMMSI

func DecodeMMSI(m uint32) string

DecodeMMSI returns a string with the type of the owner of the MMSI and its country Some MMSIs aren't valid. There is some more information in some MMSIs (the satellite equipment of the ship). We may add them in the future. Have a look at http://en.wikipedia.org/wiki/Maritime_Mobile_Service_Identity

func GetReferenceTime

func GetReferenceTime(payload string) (time.Time, error)

GetReferenceTime takes [the payload of] an AIS Base Station message (type 4) and returns the time data of it. It is a separate function from DecodeBaseStationReport because it can be useful to set a timeframe for our received AIS messages.

func MessageType

func MessageType(payload string) uint8

MessageType returns the type of an AIS message

func Nmea183ChecksumCheck

func Nmea183ChecksumCheck(sentence string) bool

Nmea183ChecksumCheck performs a checksum check for NMEA183 sentences. AIS messages are NMEA183 encoded.

func Router

func Router(in chan string, out chan Message, failed chan FailedSentence)

Router accepts AIS radio sentences and process them. It checks their checksum, and AIS identifiers. If they are valid it tries to assemble the payload if it spans on multiple sentences. Upon success it returns the AIS Message at the out channel. Failed sentences go to the err channel. If the in channel is closed, then it sends a message with type 255 at the out channel. Your function can check for this message to know when it is safe to exit the program.

Types

type BaseStationReport

type BaseStationReport struct {
	Repeat   uint8
	MMSI     uint32
	Time     time.Time
	Accuracy bool
	Lon      float64
	Lat      float64
	EPFD     uint8 // Enum type
	RAIM     bool
	Radio    uint32
}

A BaseStationReport is a decoded AIS base station report (message type 4)

func DecodeBaseStationReport

func DecodeBaseStationReport(payload string) (BaseStationReport, error)

DecodeBaseStationReport decodes the payload of a Type 4 AIS message

func (BaseStationReport) String

func (m BaseStationReport) String() string

PrintBaseStationReport returns a formatted string of a BaseStationReport. Mainly to help developers with understanding base position reports.

type BinaryBroadcast

type BinaryBroadcast struct {
	Repeat uint8
	MMSI   uint32
	DAC    uint16
	FID    uint8
	Data   string
}

BinaryBroadcast is a Type 8 message

func DecodeBinaryBroadcast

func DecodeBinaryBroadcast(payload string) (BinaryBroadcast, error)

DecodeBinaryBroadcast decodes [the payload of] an AIS Binary Broadcast message (Type 8) but not its binary payload

func (BinaryBroadcast) String

func (m BinaryBroadcast) String() string

PrintBinaryBroadcast returns a string with some data for a Binary Broadcast message

type ClassAPositionReport

type ClassAPositionReport struct {
	PositionReport
	RAIM     bool    // RAIM flag
	Radio    uint32  // Radio status
	Status   uint8   // navigation status (enumerated type)
	Turn     float32 // rate of turn - ROT (sc - Special Calc I3)
	Maneuver uint8   // maneuver indicator (enumerated)
}

A ClassAPositionReport is a decoded AIS position message (messages of type 1, 2 or 3). Please have a look at http://catb.org/gpsd/AIVDM.html and at http://www.navcen.uscg.gov/?pageName=AISMessagesA

func DecodeClassAPositionReport

func DecodeClassAPositionReport(payload string) (ClassAPositionReport, error)

DecodeClassAPositionReport decodes [the payload of] an AIS position message (type 1/2/3)

func (ClassAPositionReport) String

func (m ClassAPositionReport) String() string

PrintClassAPositionReport returns a formatted string with the detailed data of a AIS position message. Its main use is to act as a guide for any developer wishing to correctly parse an AIS position message, since some parts of a message are enumareted, and other parts although they mainly are numeric values, for certain values they can have a non-numeric meaning.

type ClassBPositionReport

type ClassBPositionReport struct {
	PositionReport
	RAIM     bool   // RAIM flag
	Radio    uint32 // Radio status
	CSUnit   bool
	Display  bool
	DSC      bool
	Band     bool
	Msg22    bool
	Assigned bool
}

A ClassBPositionReport is a decoded AIS position message (type 18).

func DecodeClassBPositionReport

func DecodeClassBPositionReport(payload string) (ClassBPositionReport, error)

DecodeClassBPositionReport decodes [the payload of] an AIS position message (type 18)

func (ClassBPositionReport) String

func (m ClassBPositionReport) String() string

PrintClassBPositionReport returns a formatted string with the detailed data of a AIS position message. Its main use is to act as a guide for any developer wishing to correctly parse an AIS position message, since some parts of a message are enumareted, and other parts although they mainly are numeric values, for certain values they can have a non-numeric meaning.

type ExtendedClassBPositionReport

type ExtendedClassBPositionReport struct {
	PositionReport
	VesselName  string
	ShipType    uint8
	ToBow       uint16 // Dimension to bow
	ToStern     uint16 // Dimension to stern
	ToPort      uint8  // Dimension to port
	ToStarboard uint8  // Dimension to starboard
	EPFD        uint8  // Position Fix Type (enumeration declared at basestationreport.go)
	RAIM        bool   // RAIM flag
}

A ExtendedClassBPositionReport is a decoded AIS position message (type 19).

func DecodeExtendedClassBPositionReport

func DecodeExtendedClassBPositionReport(payload string) (ExtendedClassBPositionReport, error)

DecodeExtendedClassBPositionReport decodes [the payload of] an AIS extendedposition message (type 19)

type FailedSentence

type FailedSentence struct {
	Sentence string
	Issue    string
}

FailedSentence includes an AIS sentence that failed to process (e.g wrong checksum) and the reason it failed.

type Message

type Message struct {
	Type    uint8
	Payload string
	Padding uint8
}

A Message stores the important properties of a AIS message, including only information useful for decoding: Type, Payload, Padding Bits A Message should come after processing one or more AIS radio sentences (checksum check, concatenate payloads spanning across sentences, etc).

type PositionReport

type PositionReport struct {
	Type     uint8
	Repeat   uint8
	MMSI     uint32
	Speed    float32 // speed over ground - SOG (sc U3)
	Accuracy bool    // position accuracy
	Lon      float64 // (sc I4)
	Lat      float64 // (sc I4)
	Course   float32 //course over ground - COG (sc U1)
	Heading  uint16  // true heading - HDG
	Second   uint8   // timestamp
}

A PositionReport is the generic structure of a Position Report, containing the common fields between Class A and B reports.

type StaticDataReport

type StaticDataReport struct {
	Repeat uint8
	MMSI   uint32
	PartNo uint8
	//PartA
	VesselName string
	//PartB
	ShipType      uint8
	VendorID      string
	UnitModelCode uint8
	SerialNumber  uint32
	CallSign      string
	// optional with MothershipMMSI
	ToBow          uint16 // Dimension to bow
	ToStern        uint16 // Dimension to stern
	ToPort         uint8  // Dimension to port
	ToStarboard    uint8  // Dimension to starboard
	MothershipMMSI uint32
}

A StaticDataReport is a decoded AIS static data report (message type 24)

func DecodeStaticDataReport

func DecodeStaticDataReport(payload string) (StaticDataReport, error)

DecodeStaticDataReport decodes the payload of a Type 24 AIS message

type StaticVoyageData

type StaticVoyageData struct {
	Repeat      uint8
	MMSI        uint32
	AisVersion  uint8
	IMO         uint32 // IMO Ship ID number
	Callsign    string
	VesselName  string
	ShipType    uint8
	ToBow       uint16    // Dimension to bow
	ToStern     uint16    // Dimension to stern
	ToPort      uint8     // Dimension to port
	ToStarboard uint8     // Dimension to starboard
	EPFD        uint8     // Position Fix Type (enumeration declared at basestationreport.go)
	ETA         time.Time // Not reliable
	Draught     uint8     // Meters/10
	Destination string
	DTE         bool
}

StaticVoyageData is a type 5 AIS message (static and voyage related data) ETA is not reliable

func DecodeStaticVoyageData

func DecodeStaticVoyageData(payload string) (StaticVoyageData, error)

DecodeStaticVoyageData decodes [the payload of] an AIS Static and Voyage Related Data message (type 5)

func (StaticVoyageData) String

func (m StaticVoyageData) String() string

PrintStaticVoyageData returns a formatted string with the detailed data of a AIS Static and Voyage Related Data (message type 5). Its main use is to act as a guide for any developer wishing to correctly parse an AIS type 5 message since some parts are enumareted, and other parts although they mainly are numeric values, for certain values they can have a non-numeric meaning.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL