From 8127c8f927b79ef29a43ebd9c9dc1b13ae5dccae Mon Sep 17 00:00:00 2001 From: "Gary E. Miller" Date: Mon, 19 Nov 2018 17:12:51 -0800 Subject: www: change .txt to .adoc. To make it clear these are asciidoc files, not plain text. --- www/AIVDM.adoc | 5438 ++++++++++++++++++++++++++++++++++++++ www/AIVDM.txt | 5438 -------------------------------------- www/NMEA.adoc | 2622 ++++++++++++++++++ www/NMEA.txt | 2622 ------------------ www/client-howto.adoc | 642 +++++ www/client-howto.txt | 642 ----- www/gpsd-time-service-howto.adoc | 1867 +++++++++++++ www/gpsd-time-service-howto.txt | 1867 ------------- www/protocol-evolution.adoc | 599 +++++ www/protocol-evolution.txt | 599 ----- www/protocol-transition.adoc | 450 ++++ www/protocol-transition.txt | 450 ---- www/time-service-intro.adoc | 351 +++ www/time-service-intro.txt | 351 --- 14 files changed, 11969 insertions(+), 11969 deletions(-) create mode 100644 www/AIVDM.adoc delete mode 100644 www/AIVDM.txt create mode 100644 www/NMEA.adoc delete mode 100644 www/NMEA.txt create mode 100644 www/client-howto.adoc delete mode 100644 www/client-howto.txt create mode 100644 www/gpsd-time-service-howto.adoc delete mode 100644 www/gpsd-time-service-howto.txt create mode 100644 www/protocol-evolution.adoc delete mode 100644 www/protocol-evolution.txt create mode 100644 www/protocol-transition.adoc delete mode 100644 www/protocol-transition.txt create mode 100644 www/time-service-intro.adoc delete mode 100644 www/time-service-intro.txt (limited to 'www') diff --git a/www/AIVDM.adoc b/www/AIVDM.adoc new file mode 100644 index 00000000..e4eb929c --- /dev/null +++ b/www/AIVDM.adoc @@ -0,0 +1,5438 @@ += AIVDM/AIVDO protocol decoding = +:description: The AIVDM Marine AIS protocol demystified, for programmers. +:keywords: AIS, AIVDM, AIVDO, standard, protocol, Automatic Identification System +Eric S. Raymond +v1.52, Aug 2016 + +This document is mastered in asciidoc format. If you are reading it in HTML, +you can find the original at the GPSD project website + +// If you are reading the asciidoc master of this document, the +// occasional comments led with '//!' are hints for GPSD developer tools +// that use the table layouts to generate code. + +If you find this document useful - and especially if it helps you make +money - please contribute to maintaining it by supporting the author's +full-time open-source work through <>. Even a few dollars a +week can make a difference. + +== Introduction == + +This is a description of how to decode AIVDM/AIVDO sentences. It +collects and integrates information from publicly available sources +and is intended to assist developers of open-source software for +interpreting these messages. + +AIVDM/AIVDO sentences are emitted by receivers for AIS, the marine +Automatic Identification System. AIS transmitters are fitted to +vessels, navigation markers, and certain types of shore station. They +periodically squawk their position (and course, when applicable), using +TDMA (Time Division Multiple Access) technology similar to the way +cellphones do to avoid mutual interference. AIS receivers make this data +available for navigation, anti-collision systems, and other uses. + +The International Maritime Organization's (IMO) International +Convention for the Safety of Life at Sea (SOLAS) requires operating AIS +transmitters on all international cargo vessels of more than 300 tons +displacement, all cargo vessels of more than 500 tons displacement, +and all passenger vessels; see <> for details. Individual +maritime nations may have stricter and more detailed rules: for those +obtaining in U.S. waters, see <>. + +AIS receivers report ASCII data packets as a byte stream over serial +or USB lines, using the NMEA 0183 or NMEA 2000 data formats. The RS422 +variant of serial specified as a physical layer by NMEA 0183 is common +in marine navigation systems; there may be a "pilot plug" +<> which converts to USB. Alternatively, newer AIS +receivers may report directly over RS232 or USB. + +AIS packets have the introducer "!AIVDM" or "!AIVDO"; AIVDM packets +are reports from other ships and AIVDO packets are reports from your +own ship. + +A lengthy description of AIS, focusing on the goals and history of the +system, but not describing the data protocols in any detail, can be +found at <>. + +== Standards == + +Multiple standards bear on the AIVDM/AIVDO format. This document +exists because assembling them into a complete picture is technically +difficult and was long impeded by legal barriers as well. + +ITU Recommendation M.1371, "Technical Characteristics for a Universal +Shipborne Automatic Identification System Using Time Division Multiple +Access" <>, issued in 2001, first described the bit-level +format of AIS radio messages. This standard was proprietary and +expensive when issued. I did not have access to it or any of its +followup revisions while assembling versions of this document up to +1.29. + +ITU-R M.1371 was expanded and clarified by "IALA Technical +Clarifications on Recommendation ITU-R M.1371-1" <>, which +is freely available. + +There have been three minor revisions of ITU-R M.1371 since it was +originally issued. These add interpretations to packet bitfields that +were previously marked "spare" and "regional reserved". ITU-R M.1371 +revision 4 became available for free download, apparently at some +point in early 2011, well after most of this document was assembled. + +The ASCII format for AIVDM/AIVDO representations of AIS radio messages +seems to have been set by IEC-PAS 61162-100, "Maritime navigation and +radiocommunication equipment and systems" <>. It is +proprietary and I have not looked at it. Various public sources +indicate that it has been "harmonized" with some version of NMEA 0183, +which I also have not looked at because it too is proprietary and +expensive, and surrounded by rapacious attack lawyers. + +== Information Sources == + +Together, the IALA Technical Clarifications at <> and the +Coast Guard's AIS pages at <> describe AIS message payloads +type 1-24 almost completely. Certain specialized binary messages of +types 6 and 8 defined by the International Maritime Organization are +described in <> and <>. The detail information on +payload formats in this document is mostly derived from these public +sources. + +Kurt Schwehr is a research scientist at the Center for Coastal and +Ocean Mapping at the University of New Hampshire. Much of his research +involves AIS. His work blog at <> contains sample messages +and descriptions of AIS operation in the wild that shed light on +various obscure corners of the specification. He has explained the +otherwise undocumented Repeat Indicator field and USCG extended AIVDM +to me by email. He also communicated some critical information from +<>, and supplied information about new messages and fields in +ITU-1371-3. + +Descriptions of messages 25 and 26 are based on AIS transceiver vendor +documentation was originally forwarded to me by a source wishing to +remain anonymous; I later checked them against ITU1371-4. Message +type 27 was described in ITU1371-4 and added here after that became a +freely available download. + +Should you set out to write a decoder using this document, you are +likely to find that one of your challenges is finding enough AIS +packet data to make an effective regression test -- especially if you +live out of line of sight of any ship traffic and would get nothing +from running an AIS receiver. Fortunately, various AIS sites offer +live feeds over the Internet that aggregate AIS streams from all over +the world. Some charge subscriptions; others offer time-delayed access +for free and charge for a real-time feed. Still others are pool sites; +you join by contributing your feed and receive all feeds. + +AIS Hub (<>) is a free, public AIS feed pool. It provides +exchange of AIS data in raw NMEA format; all AISHub members share +their own received AIS data and receive the merged feed from all other +participating parties. It is open-source friendly, offering a Linux +port in source of its software for collecting and forwarding AIS +data. Peter Stoyanov and the other AIS Hub principals have generously +donated a live feed to the GPSD project despite the fact that I live +60 miles inland and cannot send them anything interesting. + +Some of what this document explains about the quirks of real-world +encoders comes from examples provided by Kurt Schwehr. Other such +information, especially for the less common sentences, comes from +inspection of sentences forwarded to me from AIS Hub by various +interested parties, and more recently from AIS Hub itself. + +== Improving This Document == + +To avoid copyright difficulties, I rely only on freely redistributable +public documents and paraphrased reports from people who have seen the +relevant proprietary standards. If you are such a person, please help +by reporting the following to be included in future versions of this +document: + +* Sample sentences of types 16-17, 22-23, and 25-27. + +* Sample sentences of type 6 and 8 conforming to <>, + <>, and <>. + +For verification purposes, I need the raw sentences together with +decoded dumps of their field values. Please note that sample +sentences not accompanied by field dumps are *not* useful; I can get +plenty of those. + +== Open-Source Implementations == + +The GPSD project ships an AIVDM/AIVDO sentence decoder as part of the +daemon. This document was developed to be the specification for it, +and it will decode all sentence type described herein. + +The source-code repository of the GPSD project holds a conforming +standalone Python decoder, ais.py, that is not included in shipped +releases. It may be useful for developers working in that language. + +<> includes links to a collection of Python scripts for +decoding and analyzing AIVDM sentences. Kurt Schwehr warns that this +is research code rather than a production tool. + +There is a http://gnuais.sourceforge.net/[GNU AIS] project at +SourceForge. It seems intended primarily to work directly +with AIS radios. + +http://www.maritec.co.za/aisvdmvdodecoding.php[The Maritec decoder] +looks to be pretty high-quality and can be exercised through a +public web form. This is a useful resource for anyone qualifying +an AIS decoder. + +== AIVDM/AIVDO Sentence Layer == + +AIVDM/AIVDO is a two-layer protocol. The outer layer is a variant of +NMEA 0183, the ancient standard for data interchange in marine +navigation systems; NMEA 0183 is described at <>. + +Here is a typical AIVDM data packet: + +-------------------------------------------------------------------- +!AIVDM,1,1,,B,177KQJ5000G?tO`K>RA1wUbN0TKH,0*5C +-------------------------------------------------------------------- + +And here is what the fields mean: + +Field 1, !AIVDM, identifies this as an AIVDM packet. + +Field 2 (1 in this example) is the count of fragments in the currently +accumulating message. The payload size of each sentence is limited by +NMEA 0183's 82-character maximum, so it is sometimes required to split +a payload over several fragment sentences. + +Field 3 (1 in this example) is the fragment number of this +sentence. It will be one-based. A sentence with a fragment count of +1 and a fragment number of 1 is complete in itself. + +Field 4 (empty in this example) is a sequential message ID for +multi-sentence messages. + +Field 5 (B in this example) is a radio channel code. AIS uses the high +side of the duplex from two VHF radio channels: AIS Channel A is +161.975Mhz (87B); AIS Channel B is 162.025Mhz (88B). In the wild, +channel codes '1' and '2' may also be encountered; the standards +do not prescribe an interpretation of these but it's obvious enough. + +Field 6 (177KQJ5000G?tO`K>RA1wUbN0TKH in this example) is the data +payload. We'll describe how to decode this in later sections. + +Field 7 (0) is the number of fill bits requires to pad the data +payload to a 6 bit boundary, ranging from 0 to 5. Equivalently, +subtracting 5 from this tells how many least significant bits of the +last 6-bit nibble in the data payload should be ignored. Note that +this pad byte has a tricky interaction with the <<>> +requirement for byte alignment in over-the-air AIS messages; see the +detailed discussion of message lengths and alignment in a later +section. + +The \*-separated suffix (\*5C) is the NMEA 0183 data-integrity checksum +for the sentence, preceded by "*". It is computed on the entire +sentence including the AIVDM tag but excluding the leading "!". + +For comparison, here is an example of a multifragment sentence with a +nonempty message ID field: + +-------------------------------------------------------------------- +!AIVDM,2,1,3,B,55P5TL01VIaAL@7WKO@mBplU@>, the valid ASCII characters for +this encoding begin with "0" (64) and end with "w" (87); however, the +intermediate range "X" (88) to "\_" (95) is not used. + +.ASCII payload armoring +[width="25%",frame="topbot",options="header"] +|====================================== +| Char |ASCII |Decimal |Bits +|"0" | 48 | 0 |000000 +|"1" | 49 | 1 |000001 +|"2" | 50 | 2 |000010 +|"3" | 51 | 3 |000011 +|"4" | 52 | 4 |000100 +|"5" | 53 | 5 |000101 +|"6" | 54 | 6 |000110 +|"7" | 55 | 7 |000111 +|"8" | 56 | 8 |001000 +|"9" | 57 | 9 |001001 +|":" | 58 |10 |001010 +|";" | 59 |11 |001011 +|"<" | 60 |12 |001100 +|"=" | 61 |13 |001101 +|">" | 62 |14 |001110 +|"?" | 63 |15 |001111 +|"@" | 64 |16 |010000 +|"A" | 65 |17 |010001 +|"B" | 66 |18 |010010 +|"C" | 67 |19 |010011 +|"D" | 68 |20 |010100 +|"E" | 69 |21 |010101 +|"F" | 70 |22 |010110 +|"G" | 71 |23 |010111 +|"H" | 72 |24 |011000 +|"I" | 73 |25 |011001 +|"J" | 74 |26 |011010 +|"K" | 75 |27 |011011 +|"L" | 76 |28 |011100 +|"M" | 77 |29 |011101 +|"N" | 78 |30 |011110 +|"O" | 79 |31 |011111 +|"P" | 80 |32 |100000 +|"Q" | 81 |33 |100001 +|"R" | 82 |34 |100010 +|"S" | 83 |35 |100011 +|"T" | 84 |36 |100100 +|"U" | 85 |37 |100101 +|"V" | 86 |38 |100110 +|"W" | 87 |39 |100111 +|"`" | 96 |40 |101000 +|"a" | 97 |41 |101001 +|"b" | 98 |42 |101010 +|"c" | 99 |43 |101011 +|"d" |100 |44 |101100 +|"e" |101 |45 |101101 +|"f" |102 |46 |101110 +|"g" |103 |47 |101111 +|"h" |104 |48 |110000 +|"i" |105 |49 |110001 +|"j" |106 |50 |110010 +|"k" |107 |51 |110011 +|"l" |108 |52 |110100 +|"m" |109 |53 |110101 +|"n" |110 |54 |110110 +|"o" |111 |55 |110111 +|"p" |112 |56 |111000 +|"q" |113 |57 |111001 +|"r" |114 |58 |111010 +|"s" |115 |59 |111011 +|"t" |116 |60 |111100 +|"u" |117 |61 |111101 +|"v" |118 |62 |111110 +|"w" |119 |63 |111111 +|====================================== + +Concatenate all six-bit quantities found in the payload, MSB first. +This is the binary payload of the sentence. + +== AIS Payload Data Types == + +Data in AIS message payloads (what you get after undoing the AIVDM/AIVDO +armoring) is encoded as bitfields in the sentence. Bitfields may be +interpreted in one of the following ways: + +- Signed or unsigned integer +- Float (scaled from signed integer) +- Flag or Boolean +- Index into a controlled vocabulary +- Reserved bits +- Spare bits +- Strings + +Numeric bitfields are interpreted as big-endian twos-complement +integers; when signed, the sign bit is the highest. + +Float fields have an associated divisor which should be applied +to convert to the correct units. In one case, the ROT field in message +types 1-3, the scaling operation involves a more elaborate formula. + +Flags are encoded as 1 for true/yes/on, 0 for false/no/off. + +Indices into controlled vocabularies are numeric bitfields which +must be interpreted using per-field string lists specified in the +standards. + +Spare fields generally seem to have been inserted in order to put +certain field starts on 8-bit boundaries, and should be ignored. Decoders +should not, however, assume that spare fields will be all zeroes. + +Reserved fields should not be ignored, as they may be assigned for +extension data in minor revisions of the AIS standard; it is noted in +the message descriptions where this has already occurred. It is good +practice for a decoder to make reserved fields available to client +applications as uninterpreted bitfields. + +Character-string fields within AIS messages are encoded in a special +way, referred to as "six-bit" in the tables below. First, chop the +string field into consecutive six-bit nibbles without padding (each +span of three 8-bit bytes includes 4 of these). Each six-bit nibble +maps to an ASCII character. Nibbles 0-31 map to the characters "@" ( +ASCII 64) through "\_" (ASCII 95) respectively; nibbles 32-63 map to +characters " " (ASCII 32) though "?" (ASCII 63). Lowercase ASCII +letters, the backtick, right and left curly brackets, pipe bar, tilde +and DEL cannot be encoded. + +.Sixbit ASCII +[width="25%",frame="topbot"] +|========================================================================================== +|000000 | 0 |"@" |010000 |16 |"P" |100000 |32 |" " |110000 |48 |"0" +|000001 | 1 |"A" |010001 |17 |"Q" |100001 |33 |"!" |110001 |49 |"1" +|000010 | 2 |"B" |010010 |18 |"R" |100010 |34 |""" |110010 |50 |"2" +|000011 | 3 |"C" |010011 |19 |"S" |100011 |35 |"\#" |110011 |51 |"3" +|000100 | 4 |"D" |010100 |20 |"T" |100100 |36 |"$" |110100 |52 |"4" +|000101 | 5 |"E" |010101 |21 |"U" |100101 |37 |"%" |110101 |53 |"5" +|000110 | 6 |"F" |010110 |22 |"V" |100110 |38 |"&" |110110 |54 |"6" +|000111 | 7 |"G" |010111 |23 |"W" |100111 |39 |"\'" |110111 |55 |"7" +|001000 | 8 |"H" |011000 |24 |"X" |101000 |40 |"(" |111000 |56 |"8" +|001001 | 9 |"I" |011001 |25 |"Y" |101001 |41 |")" |111001 |56 |"9" +|001010 |10 |"J" |011010 |26 |"Z" |101010 |42 |"\*" |111010 |58 |":" +|001011 |11 |"K" |011011 |27 |"[" |101011 |43 |"\+" |111011 |59 |";" +|001100 |12 |"L" |011100 |28 |"{backslash}" |101100 |44 |"," |111100 |60 |"<" +|001101 |13 |"M" |011101 |29 |"]" |101101 |45 |"-" |111101 |61 |"=" +|001110 |14 |"N" |011110 |30 |"\^" |101110 |46 |"." |111110 |62 |">" +|001111 |15 |"O" |011111 |31 |"\_" |101111 |47 |"/" |111111 |63 |"?" +|========================================================================================== + +According to the standard, trailing unused characters in six-bit +fields will be represented by "@" (six-bit zero); however, real-world +encoders are not careful about this and often have nonzero garbage +after the "@". The terminating "@" should not be considered part of +the text, and any non-"@" characters after it should be discarded. It +is also common to space-fill short fields such as ship and station +name, so a decoder should strip trailing spaces after stripping +at-signs and the garbage after them. + +Trailing string fields are often specified as "up to" a certain number of bits. +Decoders should be prepared to handle any field length up to that +number, including zero. + +== AIS Payload Interpretation == + +The following table describes message types that are international +standards from <> and its revisions. There are also local +and regional extensions used on inland waterways such as the Danube +and the Thames and in British and Irish coastal waters; pointers +to some of these are included later in this document. + +Note that many sources use 1-origin numbering for the bits. We'll +use 0-origin in this document. + +The first 6 bits of the payload (0-5) are the message type. Message +types are as follows: + +.Message types +[width="50%",frame="topbot"] +|====================================================== +|01 |Position Report Class A +|02 |Position Report Class A (Assigned schedule) +|03 |Position Report Class A (Response to interrogation) +|04 |Base Station Report +|05 |Static and Voyage Related Data +|06 |Binary Addressed Message +|07 |Binary Acknowledge +|08 |Binary Broadcast Message +|09 |Standard SAR Aircraft Position Report +|10 |UTC and Date Inquiry +|11 |UTC and Date Response +|12 |Addressed Safety Related Message +|13 |Safety Related Acknowledgement +|14 |Safety Related Broadcast Message +|15 |Interrogation +|16 |Assignment Mode Command +|17 |DGNSS Binary Broadcast Message +|18 |Standard Class B CS Position Report +|19 |Extended Class B Equipment Position Report +|20 |Data Link Management +|21 |Aid-to-Navigation Report +|22 |Channel Management +|23 |Group Assignment Command +|24 |Static Data Report +|25 |Single Slot Binary Message, +|26 |Multiple Slot Binary Message With Communications State +|27 |Position Report For Long-Range Applications +|====================================================== + +In normal operation, an AIS transceiver will broadcast a position report +(type 1, 2, or 3) every 2 to 10 seconds depending on the vessel's +speed while underway, and every 3 minutes while the vessel is at +anchor and stationary. It will send a type 5 identification every 6 +minutes. (More detail is at <>, part 2.3) + +Class 6 is used for unencrypted structured extension messages systems +conforming to the Inland AIS standard defined by <>, and by local +authorities such as the St. Lawrence Seaway and the U.S Coast Guard's +PAWSS. This document describes all of the Class 6 special message +formats approved for use in <>, <>, and <>. + +Class 8 is in common use for private encrypted messages, such as +location transmission in military exercises. It is also used for +unencrypted structured extension messages by Inland AIS, and by local +authorities such as the St. Lawrence Seaway and PAWSS. This document +describes all of the Class 8 special message formats approved for use +in <>, <>, and <>. + +Classes 12 and 14 are used for text messaging, nominally safety-related +but also for traffic control and occasionally chatter. + +In practice, message types other than 1, 3, 4, 5, 18, and 24 are +unusual or rare; many AIS transmitters never emit them. + +An MMSI is a Mobile Marine Service Identifier, a unique 9-digit ID for +the ship's radio(s). The first three digits convey information about +the country in which the ID was issued <>. US vessels +travelling solely in U.S. waters sometimes incorrectly omit the +leading "3", the geography code for North and Central America and +Caribbean, emitting 8-digit MMSIs beginning with the U.S. country code +of 669. + +According to <>, different formats of MMSI are used for +different classes of transmitter. In the format descriptions below, a +MID is a three-digit decimal literal ranging from 201 to 775 that +identifies a country or other maritime jurisdiction. See <> +for a list of MIDs. + +.MID formats +[frame="topbot",options="header"] +|============================================================================== +|8MIDXXXXX | Diver's radio (not used in the U.S. in 2013) +|MIDXXXXXX | Ship +|0MIDXXXXX | Group of ships; the U.S. Coast Guard, for example, is 03699999 +|00MIDXXXX | Coastal stations +|111MIDXXX | SAR (Search and Rescue) aircraft +|99MIDXXXX | Aids to Navigation +|98MIDXXXX | Auxiliary craft associated with a parent ship +|970MIDXXX | AIS SART (Search and Rescue Transmitter) +|972XXXXXX | MOB (Man Overboard) device +|974XXXXXX | EPIRB (Emergency Position Indicating Radio Beacon) AIS +|============================================================================== + +Detailed descriptions of message types 1-24 follow. Message types 1-22 +are derived from <>. Message type 23 was described to me by Mike +Greene based on <>. Message type 24 was described to me by +<>, whose Python toolkit decodes it. Message types 25-26 are +reported by <>, who observes they were added in Version 3 of +<>. Message type 27 is direct from <> version 4. + +The "Member" column in these tables is not derived from any of the ITU +standards or amendments. I have invented it in order to be able to +describe a lossless textual encoding of AIS sentences in JSON. These +names are also chosen for suitability as structure/object member names +in computer languages, so that application programming interfaces +across different languages can have a common and readily intelligible +set to use. + +The "T" column declares the data type of the field, and may have +any of the values in the following table. It is intended to be used +for generating bitfield-extraction code directly from the message +type descriptions. + +[frame="topbot",options="header"] +|============================================================================== +|u| Unsigned integer +|U| Unsigned integer with scale - renders as float, suffix is decimal places +|i| Signed integer +|I| Signed integer with scale - renders as float, suffix is decimal places +|b| Boolean +|e| Enumerated type (controlled vocabulary) +|x| Spare or reserved bit +|t| String (packed six-bit ASCII) +|d| Data (uninterpreted binary) +|a| Array boundary, numeric suffix is maximum array size. + ^ before suffix means preceding fields is the length. + Following fields are repeated to end of message +|============================================================================== + +The field breakdowns in this document have been checked against live +decoded data rendered by known-good implementations for message types +1-15, 18-21, and 24. Described but unchecked are 16-17, 22-23, and +25-27. Also, the interpretation of IMO extension subtypes of messages +6 and 8 has yet to be tested. + +Bit lengths and length ranges are given because decoders should check +them against the message type. Messages with correct checksums but the +wrong payload length for their type occur with about 0.3% frequency on +AISHub; if you don't reject these, your clients will see spurious +zeros or garbage. + +=== Types 1, 2 and 3: Position Report Class A === + +Type 1, 2 and 3 messages share a common reporting structure for +navigational information; we'll call it the Common Navigation Block +(CNB). This is the information most likely to be of interest for +decoding software. Total of 168 bits, occupying one AIVDM sentence. + +//: Type CNB +.Common Navigation Block +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 1-3 +|6-7 | 2 |Repeat Indicator |repeat |u|Message repeat count +|8-37 |30 |MMSI |mmsi |u|9 decimal digits +|38-41 | 4 |Navigation Status |status |e|See "Navigation Status" +|42-49 | 8 |Rate of Turn (ROT) |turn |I3|See below +|50-59 |10 |Speed Over Ground (SOG) |speed |U1|See below +|60-60 | 1 |Position Accuracy |accuracy |b|See below +|61-88 |28 |Longitude |lon |I4|Minutes/10000 (see below) +|89-115 |27 |Latitude |lat |I4|Minutes/10000 (see below) +|116-127 |12 |Course Over Ground (COG)|course |U1|Relative to true north, + to 0.1 degree precision +|128-136 | 9 |True Heading (HDG) |heading |u|0 to 359 degrees, + 511 = not available. +|137-142 | 6 |Time Stamp |second |u|Second of UTC timestamp +|143-144 | 2 |Maneuver Indicator |maneuver |e|See "Maneuver Indicator" +|145-147 | 3 |Spare | |x|Not used +|148-148 | 1 |RAIM flag |raim |b|See below +|149-167 |19 |Radio status |radio |u|See below +|============================================================================== + +The Repeat Indicator is a directive to an AIS transceiver that this +message should be rebroadcast. This was intended as a way of getting +AIS messages around hills and other obstructions in coastal waters, +but is little used as base station coverage is more effective. It is +intended that the bit be incremented on each retransmission, to a +maximum of three hops. A value of 3 indicates "Do not repeat". + +.Navigation Status +[width="50%",frame="topbot"] +|================================================================= +|0 | Under way using engine +|1 | At anchor +|2 | Not under command +|3 | Restricted manoeuverability +|4 | Constrained by her draught +|5 | Moored +|6 | Aground +|7 | Engaged in Fishing +|8 | Under way sailing +|9 | Reserved for future amendment of Navigational Status for HSC +|10| Reserved for future amendment of Navigational Status for WIG +|11| Reserved for future use +|12| Reserved for future use +|13| Reserved for future use +|14| AIS-SART is active +|15| Not defined (default) +|================================================================= + +Note, the AIS-SART value was added after <> and designates an +AIS transmitter in an survival craft such as a lifeboat. See +<> for the field specification and <> for +background. + +Turn rate is encoded as follows: + +* 0 = not turning +* 1...126 = turning right at up to 708 degrees per minute or higher +* 1...-126 = turning left at up to 708 degrees per minute or higher +* 127 = turning right at more than 5deg/30s (No TI available) +* -127 = turning left at more than 5deg/30s (No TI available) +* 128 (80 hex) indicates no turn information available (default) + +Values between 0 and 708 degrees/min coded by ROT~AIS~=4.733 * +SQRT(ROT~sensor~) degrees/min where ROT~sensor~ is the Rate of Turn as +input by an external Rate of Turn Indicator. ROT~AIS~ is rounded to +the nearest integer value. Thus, to decode the field value, divide by 4.733 +and then square it. Sign of the field value should be preserved when +squaring it, otherwise the left/right indication will be lost. + +Speed over ground is in 0.1-knot resolution from 0 to 102 knots. +Value 1023 indicates speed is not available, value 1022 indicates +102.2 knots or higher. + +The position accuracy flag indicates the accuracy of the fix. A value of +1 indicates a DGPS-quality fix with an accuracy of < 10ms. 0, the +default, indicates an unaugmented GNSS fix with accuracy > 10m. + +Longitude is given in in 1/10000 min; divide by 600000.0 to obtain +degrees. Values up to plus or minus 180 degrees, East = positive, West +\= negative. A value of 181 degrees (0x6791AC0 hex) indicates that +longitude is not available and is the default. + +Latitude is given in in 1/10000 min; divide by 600000.0 to obtain +degrees. Values up to plus or minus 90 degrees, North = positive, +South = negative. A value of 91 degrees (0x3412140 hex) indicates +latitude is not available and is the default. + +Course over ground will be 3600 (0xE10) if that data is not available. + +Seconds in UTC timestamp should be 0-59, except for these special values: + +* 60 if time stamp is not available (default) +* 61 if positioning system is in manual input mode +* 62 if Electronic Position Fixing System operates in estimated (dead + reckoning) mode, +* 63 if the positioning system is inoperative. + +The Regional Reserved field is intended for use by local maritime +authorities. It is not known to be in any actual use up to 2009. + +The Maneuver Indicator (143-144) may have these values: + +.Maneuver Indicator +[width="50%",frame="topbot",options="header"] +|=========================================================== +|0 | Not available (default) +|1 | No special maneuver +|2 | Special maneuver (such as regional passing arrangement) +|=========================================================== + +Riverine and inland navigation systems conforming to <> +designate this field "Blue Sign" with the following enumerated +values: + +.Blue Sign +[width="50%",frame="topbot",options="header"] +|=========================================================== +|0 | Not available (default) +|1 | No +|2 | Yes +|=========================================================== + +The interpretation of bits 143-147 has been a bit unstable. In +<> and therefore in the original <>, they were +described like this: + +[width="50%",frame="topbot",options="header"] +|================================= +|Field |Len |Description +|143-145 | 3 |Regional Reserved +|146-147 | 2 |Spare +|================================= + +The interpretation of 143-144 as a special maneuver field is new in +revision 3 of <>. + +The RAIM flag indicates whether Receiver Autonomous Integrity +Monitoring is being used to check the performance of the EPFD. +0 = RAIM not in use (default), 1 = RAIM in use. See <> for +a detailed description of this flag. + +Bits 149-167 are diagnostic information for the radio system. Consult +<> for detailed description of the latter. + +=== Type 4: Base Station Report === + +This message is to be used by fixed-location base stations to +periodically report a position and time reference. Total of 168 bits, +occupying one AIVDM sentence. + +The standard uses "EPFD" to designate any Electronic Position Fixing Device. + +//: Type 4 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 4 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |MMSI |mmsi |u|9 decimal digits +|38-51 | 14 |Year (UTC) |year |u|UTC, 1-9999, 0 = N/A (default) +|52-55 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) +|56-60 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|61-65 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|66-71 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|72-77 | 6 |Second (UTC) |second |u|0-59; 60 = N/A (default) +|78-78 | 1 |Fix quality |accuracy |b|As in Common Navigation Block +|79-106 | 28 |Longitude |lon |I4|As in Common Navigation Block +|107-133 | 27 |Latitude |lat |I4|As in Common Navigation Block +|134-137 | 4 |Type of EPFD |epfd |e|See "EPFD Fix Types" +|138-147 | 10 |Spare | |x|Not used +|148-148 | 1 |RAIM flag |raim |b|As for common navigation block +|149-167 | 19 |SOTDMA state |radio |u|As in same bits for Type 1 +|============================================================================== + +.EPFD Fix Types +[width="50%",frame="topbot",options="header"] +|=================================== +|Code |Position Fix Type +|0 |Undefined (default) +|1 |GPS +|2 |GLONASS +|3 |Combined GPS/GLONASS +|4 |Loran-C +|5 |Chayka +|6 |Integrated navigation system +|7 |Surveyed +|8 |Galileo +|=================================== + +Note: though values 9-15 are marked "not used" in <>, the EPFD +type value 15 (all field bits 1) is not uncommon in the wild; it +appears some receivers emit it as the undefined value. Decoders should +be prepared to accept this. + +=== Type 5: Static and Voyage Related Data === + +Message has a total of 424 bits, occupying two AIVDM sentences. + +In practice, the information in these fields (especially ETA and +destination) is not reliable, as it has to be hand-updated by +humans rather than gathered automatically from sensors. + +Also note that it is fairly common in the wild for this message to +have a wrong bit length (420 or 422). Robust decoders should ignore +trailing garbage and deal gracefully with a slightly truncated +destination field. + +//: Type 5 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member/Type |T|Encoding +|0-5 | 6 |Message Type |type |u|Constant: 5 +|6-7 | 2 |Repeat Indicator |repeat |u|Message repeat count +|8-37 | 30 |MMSI |mmsi |u|9 digits +|38-39 | 2 |AIS Version |ais_version |u|0=<>, + 1-3 = future editions +|40-69 | 30 |IMO Number |imo |u|IMO ship ID number +|70-111 | 42 |Call Sign |callsign |t|7 six-bit characters +|112-231 |120 |Vessel Name |shipname |t|20 six-bit characters +|232-239 | 8 |Ship Type |shiptype |e|See "Codes for Ship Type" +|240-248 | 9 |Dimension to Bow |to_bow |u|Meters +|249-257 | 9 |Dimension to Stern |to_stern |u|Meters +|258-263 | 6 |Dimension to Port |to_port |u|Meters +|264-269 | 6 |Dimension to Starboard |to_starboard |u|Meters +|270-273 | 4 |Position Fix Type |epfd |e|See "EPFD Fix Types" +|274-277 | 4 |ETA month (UTC) |month |u|1-12, 0=N/A (default) +|278-282 | 5 |ETA day (UTC) |day |u|1-31, 0=N/A (default) +|283-287 | 5 |ETA hour (UTC) |hour |u|0-23, 24=N/A (default) +|288-293 | 6 |ETA minute (UTC) |minute |u|0-59, 60=N/A (default) +|294-301 | 8 |Draught |draught |U1|Meters/10 +|302-421 |120 |Destination |destination |t|20 6-bit characters +|422-422 | 1 |DTE |dte |b|0=Data terminal ready, + 1=Not ready (default). +|423-423 | 1 |Spare | |x|Not used +|============================================================================== + +<> specifies the following: + +* the IMO Number field should be zeroed for inland vessels. +* ATIS code should be used for inland vessels +* ship dimensions should be set to the maximum rectangle size of the convoy +* draught information should be rounded up to nearest decimeter +* For the destination, UN/LOCODE and ERI terminal codes should be used + +Ship dimensions will be 0 if not available. For the dimensions to bow +and stern, the special value 511 indicates 511 meters or greater; for +the dimensions to port and starboard, the special value 63 indicates +63 meters or greater. + +.Codes for Ship Type +[width="50%",frame="topbot",options="header"] +|============================================================== +|Code |Ship & Cargo Classification +|0 |Not available (default) +|1-19 |Reserved for future use +|20 |Wing in ground (WIG), all ships of this type +|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), all ships of this type +|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, all ships of this type +|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, all ships of this type +|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, all ships of this type +|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, all ships of this 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 +|============================================================== + +Note that garbage values greater than 99 are supposed to be unused, +but are not uncommon in the wild; AIS transmitters seem prone to put +junk in this field when it's not explicitly set. Decoders should +treat these like value 0 rather than throwing an exception until and +unless the controlled vocabulary is extended to include the unknown +values. + +=== Type 6: Binary Addressed Message === + +Message type 6 is an addressed point-to-point message with unspecified +binary payload. The St. Lawrence Seaway AIS system, the USG PAWSS +system, and the Port Authority of London use this payload for local +extension messages. <> and <> describe payload use as +international extension messages. This type is variable in length up +to a maximum of 1008 bits (up to 5 AIVDM sentence payloads). + +//: Type 6 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default) + 1 = retransmitted +|71 | 1 |Spare | |x|Not used +|72-81 | 10 |Designated Area Code |dac |u|Unsigned integer +|82-87 | 6 |Functional ID |fid |u|Unsigned integer +|88 |920 |Data |data |d|Binary data + May be shorter than 920 bits. +|============================================================================== + +Interpretation of the binary payload is controlled by: + +* The Designated Area Code, which is a jurisdiction code: 366 for the + United States. It uses the same encoding as the area designator in + MMMSIs; see <>. 1 designates international (ITU) messages. + +* The FID, which is the Functional ID for a message subtype. In some + sources this is abbreviated FI. + +The following is a non-exhaustive list of standardized DAC-FID pairs +in use for type 6. + +|============================================================================== +| DAC |FID | Source | Status | Description +| 1 | 12 | <> | Deprecated | Dangerous cargo indication +| 1 | 14 | <> | Deprecated | Tidal window +| 1 | 16 | <> | Deprecated/In Use| Number of persons on board +| 1 | 16 | <> | Standard | Number of persons on board +| 1 | 18 | <> | Standard | Clearance time to enter port +| 1 | 20 | <> | Standard | Berthing data (addressed) +| 1 | 23 | <> | In use | Area notice (addressed) +| 1 | 25 | <> | Standard | Dangerous Cargo indication +| 1 | 28 | <> | Standard | Route info addressed +| 1 | 30 | <> | Standard | Text description addressed +| 1 | 32 | <> | Standard | Tidal Window +| 200 | 21 | <> | Standard | ETA at lock/bridge/terminal +| 200 | 22 | <> | Standard | RTA at lock/bridge/terminal +| 200 | 55 | <> | Standard | Number of persons on board +| 235 | 10 | <> | In use | AtoN monitoring data (UK) +| 250 | 10 | <> | In use | AtoN monitoring data (ROI) +|============================================================================== + +DAC/FID pairs are assigned separately per message type. + +Note that the apparent presence of one of these DAC/FID pairs does +not guarantee that the message is structured. Decoders should +perform range validation on the structured fields and interpret the +message as unstructured if any check fails. (As of Aug 2014 no such +collisions have been in the wild; but see the parallel note for Type 8.) + +A list of binary layouts for selected subtypes of message 6 follows. + +==== IMO236 Dangerous Cargo Indication ==== + +This message should be used as a response to a request for Dangerous +Cargo Indication from a competent authority. The message content is +used to identify the port where the documents for the dangerous goods +cargo can be found, e. g. last and next port of call, and to allow +the requesting authority to form a danger estimate. + +A message 6 subtype. DAC = 001 FID = 12. Fixed length: 360 bits. +This is the <> version, now deprecated; there is a later +<> version. + +//: Type 6(1/12) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit|u|0 = no retransmit (default), + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 12 +|88-117 | 30 |Last Port Of Call |lastport |t|5 6-bit characters, UN locode +|118-121 | 4 |ETA month (UTC) |lmonth |u|1-12, 0=N/A (default) +|122-126 | 5 |ETA day (UTC) |lday |u|1-31, 0=N/A (default) +|127-131 | 5 |ETA hour (UTC) |lhour |u|0-23, 24=N/A (default) +|132-137 | 6 |ETA minute (UTC) |lminute |u|0-59, 60=N/A (default) +|138-167 | 30 |Next Port Of Call |nextport |t|5 6-bit characters, UN locode +|168-171 | 4 |ETA month (UTC) |nmonth |u|1-12, 0=N/A (default) +|172-176 | 5 |ETA day (UTC) |nday |u|1-31, 0=N/A (default) +|177-181 | 5 |ETA hour (UTC) |nhour |u|0-23, 24=N/A (default) +|182-187 | 6 |ETA minute (UTC) |nminute |u|0-59, 60=N/A (default) +|188-307 |120 |Main Dangerous Good |dangerous |t|20 6-bit characters +|308-331 | 24 |IMD Category |imdcat |t|4 6-bit characters +|332-344 | 13 |UN Number |unid |u|1-3363 UN Number +|345-354 | 10 |Amount of Cargo |amount |u|Unsigned integer +|355-356 | 2 |Unit of Quantity |unit |e|See "Cargo Unit Codes" +|357-359 | 3 |Spare | |x|Not used +|============================================================================== + +.Cargo Unit Codes +[width="50%",frame="topbot",options="header"] +|=================================== +|Code |Unit +|0 |Not available (default) +|1 |kg +|2 |metric tons +|3 |metric kilotons +|=================================== + +==== IMO236 Tidal Window ==== + +This message should be used by shore stations to inform vessels about +tidal windows which allow a vessel the safe passage of a fairway. The +message includes 1-3 predictions of current speed and current direction. +Acknowledgment is required. + +A message 6 subtype. DAC = 001 FID = 14. Variable length: 190-376 bits +This is the <> version; there is an <> version with +different widths for the latitude, longitude, and current-speed fields +(also the order of lat/lon is swapped). + +//: Type 6(1/14) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|See Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default), + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 14 +|88-91 | 4 |Month |month |u|1-12; 0 = N/A (default) +|92-96 | 5 |Day |day |u|1-31; 0 = N/A (default) +|97 | | |tidals |a3|Tidal information array +|0-26 | 27 |Latitude |lat |I4|Unit = minutes * 0.0001, + 91000 = N/A (default), + N positive, S negative. +|27-54 | 28 |Longitude |lon |I4|Unit = minutes * 0.0001, + 181000 = N/A (default), + E positive, W negative. +|55-59 | 5 |From UTC Hour |from_hour |u|0-23, 24 = N/A (default) +|60-65 | 6 |From UTC Minute |from_min |u|0-59, 60 = N/A (default) +|66-70 | 5 |To UTC Hour |to_hour |u|0-23, 24 = N/A (default) +|71-76 | 6 |To UTC Minute |to_min |u|0-59, 60 = N/A (default) +|77-85 | 9 |Current Dir. Predicted |cdir |u|0-359 deg, 360-N/A (default) +|86-92 | 7 |Current Speed Predicted|cspeed |U1|0-126, units of 0.1 knots, + 127 = N/A (default). +|============================================================================= + +The group of fields from longitude on may repeat twice more to convey up to +three points of tidal information. + +==== IMO236 Number of persons on board ==== + +This message should be used by a ship to report the number of persons +on board, e.g. on request by a competent authority. Acknowledgement +required. + +A message 6 subtype. DAC = 001 FID = 16. + +<> describes a fixed-length, 72-bit message with this layout: + +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 16 +|55-68 | 14 |# persons on board |persons |u|Unsigned integer + 0 = N/A (default) + 8191 = >= 8191 persons. +|69-71 | 3 |Spare | |x|Not used +|============================================================================== + +OPEN-QUESTION: Note that though this is a message 6 subtype and +described in <> with the attribute "addressed", there is no +destination address. A strikeout in <> suggests that this was +originally a subtype of 8. It would be good defensive implementation +for a decoder to accept either. Bit length may be used to distinguish +them. + +<> describes a fixed-length, 136-bit message with this layout: + +//: Type 6(1/16) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default), + 1 = retransmitted. +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 16 +|88-100 | 13 |# persons on board |persons |u|Unsigned integer, + 0 = N/A (default), + 8191 = >= 8191 persons. +|101-135 | 35 |Spare | |x|Not used +|============================================================================== + +==== IMO289 Clearance Time To Enter Port ==== + +This message provides specific ships with information on the port to call and +time to enter. It should be transmitted by an authority competent to grant +use of the port. + +A message 6 subtype. DAC = 001 FID = 18. Fixed length: 360 bits. + +//: Type 6(1/18) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit |b|0 = no retransmit (default), + 1 = retransmitted. +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 18 +|88-97 | 10 |Message Linkage ID |linkage |u|Unsigned integer +|98-101 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) +|102-106 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|107-111 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|112-117 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|118-237 |120 |Name of Port & Berth |portname |t|20 6-bit characters +|238-267 | 30 |Destination |destination|t|5 6-bit characters +|268-292 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, + 181000 = N/A (default). +|293-316 | 24 |Latitude |lat |I3|Unit = minutes * 0.001, + 91000 = N/A (default). +|317-359 | 43 |Spare | |x|Not used +|============================================================================== + +==== IMO 289 Berthing Data (addressed) ==== + +This message provides information on the ship's berth. If sent from a +ship it is a berthing request; if it is transmitted by a competent +authority it is a berthing assignment. + +A message 6 subtype. DAC = 001 FID = 20. Fixed Length: 360 bits. + +The 2-bit fields after "availability" describe services which may be +available at the berth. They are valid only if this master availability +bit is on. + +//: Type 6(1/20) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member/Type |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit |b|0 = no retransmit (default) + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|AC = 001 +|82-87 | 6 |FID |fid |u|ID = 20 +|88-97 | 10 |Message Linkage ID |linkage |u|Unsigned integer +|98-106 | 9 |Berth length |berth_length|u|In 1m steps, 1-510m, + 511 = >= 511m + 0 = N/A (default). +|107-114 | 8 |Berth Water Depth |berth_depth |U1|0.1-25.4m in 0.1 steps + 255 = >= 25.5m + 0 = N/A (default) +|115-117 | 3 |Mooring Position |position |e|See "Mooring Position" +|118-121 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) +|122-126 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|127-131 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|132-137 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|138-138 | 1 |Services Availability|availability|b|0 = services unknown (default) + 1 = services known +|139-140 | 2 |Agent |agent |e|See "Service Status" +|141-142 | 2 |Bunker/fuel |fuel |e|See "Service Status" +|143-144 | 2 |Chandler |chandler |e|See "Service Status" +|145-146 | 2 |Stevedore |stevedore |e|See "Service Status" +|147-148 | 2 |Electrical |electrical |e|See "Service Status" +|149-150 | 2 |Potable water |water |e|See "Service Status" +|151-152 | 2 |Customs house |customs |e|See "Service Status" +|153-154 | 2 |Cartage |cartage |e|See "Service Status" +|155-156 | 2 |Crane(s) |crane |e|See "Service Status" +|157-158 | 2 |Lift(s) |lift |e|See "Service Status" +|159-160 | 2 |Medical facilities |medical |e|See "Service Status" +|161-162 | 2 |Navigation repair |navrepair |e|See "Service Status" +|163-164 | 2 |Provisions |provisions |e|See "Service Status" +|165-166 | 2 |Ship repair |shiprepair |e|See "Service Status" +|167-168 | 2 |Surveyor |surveyor |e|See "Service Status" +|169-170 | 2 |Steam |steam |e|See "Service Status" +|171-172 | 2 |Tugs |tugs |e|See "Service Status" +|173-174 | 2 |Waste disposal (solid) |solidwaste |e|See "Service Status" +|175-176 | 2 |Waste disposal (liquid) |liquidwaste |e|See "Service Status" +|177-178 | 2 |Waste disposal (hazardous)|hazardouswaste|e|See "Service Status" +|179-180 | 2 |Reserved ballast exchange |ballast |e|See "Service Status" +|181-182 | 2 |Additional services|additional |e|See "Service Status" +|183-184 | 2 |Regional reserved 1|regional1 |e|See "Service Status" +|185-186 | 2 |Regional reserved 2|regional2 |e|See "Service Status" +|187-188 | 2 |Reserved for future|future1 |e|See "Service Status" +|189-190 | 2 |Reserved for future|future2 |e|See "Service Status" +|191-310 |120 |Name of Berth |berth_name |t|20 6-bit characters +|311-335 | 25 |Longitude |berth_lon |I3|Minutes * 0.001, + 181000 = N/A (default) +|336-359 | 24 |Latitude |berth_lat |I3|Minutes * 0.001, + 91000 = N/A (default) +|============================================================================== + +The UTC timestamp refers to the time requested or granted for berthing. + +The longitude and latitude refer to the center of the berth. + +.Mooring Position +[width="50%",frame="topbot",options="header"] +|=================================== +|Code |Position +|0 |Not available (default) +|1 |Port-side to +|2 |Starboard-side to +|3 |Mediterranean (end-on) mooring +|4 |Mooring buoy +|5 |Anchorage +|6-7 |Reserved for future use +|=================================== + +.Service Status +[width="50%",frame="topbot",options="header"] +|============================================================================= +|Code |Meaning +|0 |Not available or requested (default) +|1 |Service available +|2 |No data or unknown +|3 |Not to be used +|============================================================================= + +==== IMO289 Area Notice (addressed) ==== + +This should be used to convey time- and location-dependent information about +hazards to navigation. For information-lifetime restrictions and usage +guidance, refer to <>. + +A message 6 subtype. DAC = 001 FID = 23. 230 to 1013 bits. There is a +related Message 8 subtype for broadcast use. + +The message consists of a fixed-length header of 143 bits, followed by 1 to +10 sub-area indications which are fixed-length records 87 bits long. Here +is the message header format: + +//: Type 6(1/23) +.Area Notice (addressed) message header +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit |b|0 = no retransmit (default), + 1 = retransmitted. +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 23 +|88-97 | 10 |Message Linkage ID |linkage |u|Unsigned integer +|98-104 | 7 |Notice Description |notice |e|See "Area Notice Description" +|105-108 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) +|109-113 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|114-118 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|119-124 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|125-142 | 18 |Duration |duration |In minutes, + 262143 = N/A (default), + 0 = cancel this notice. +|143 | | |subarea |a10|Subarea array +|0-2 | 2 | |shape |u|Subarea shape +|3-86 | 85 |Subarea Payload |payload |d|Subarea payload +|============================================================================== + +The Message Linkage field is, as usual, for linking to a textual explanatory +message sent with the same linkage ID. The standard says that in this context +it has the semantics of being an identifier of or reference to an area. + +Notice description types are as follows: + +.Area Notice Description +[frame="topbot",options="header"] +|============================================================================== +| 0| Caution Area: Marine mammals habitat +| 1| Caution Area: Marine mammals in area - reduce speed +| 2| Caution Area: Marine mammals in area - stay clear +| 3| Caution Area: Marine mammals in area - report sightings +| 4| Caution Area: Protected habitat - reduce speed +| 5| Caution Area: Protected habitat - stay clear +| 6| Caution Area: Protected habitat - no fishing or anchoring +| 7| Caution Area: Derelicts (drifting objects) +| 8| Caution Area: Traffic congestion +| 9| Caution Area: Marine event +| 10| Caution Area: Divers down +| 11| Caution Area: Swim area +| 12| Caution Area: Dredge operations +| 13| Caution Area: Survey operations +| 14| Caution Area: Underwater operation +| 15| Caution Area: Seaplane operations +| 16| Caution Area: Fishery – nets in water +| 17| Caution Area: Cluster of fishing vessels +| 18| Caution Area: Fairway closed +| 19| Caution Area: Harbor closed +| 20| Caution Area: Risk (define in associated text field) +| 21| Caution Area: Underwater vehicle operation +| 22| (reserved for future use) +| 23| Environmental Caution Area: Storm front (line squall) +| 24| Environmental Caution Area: Hazardous sea ice +| 25| Environmental Caution Area: Storm warning (storm cell or line of storms) +| 26| Environmental Caution Area: High wind +| 27| Environmental Caution Area: High waves +| 28| Environmental Caution Area: Restricted visibility (fog, rain, etc.) +| 29| Environmental Caution Area: Strong currents +| 30| Environmental Caution Area: Heavy icing +| 31| (reserved for future use) +| 32| Restricted Area: Fishing prohibited +| 33| Restricted Area: No anchoring. +| 34| Restricted Area: Entry approval required prior to transit +| 35| Restricted Area: Entry prohibited +| 36| Restricted Area: Active military OPAREA +| 37| Restricted Area: Firing – danger area. +| 38| Restricted Area: Drifting Mines +| 39| (reserved for future use) +| 40| Anchorage Area: Anchorage open +| 41| Anchorage Area: Anchorage closed +| 42| Anchorage Area: Anchorage prohibited +| 43| Anchorage Area: Deep draft anchorage +| 44| Anchorage Area: Shallow draft anchorage +| 45| Anchorage Area: Vessel transfer operations +| 46| (reserved for future use) +| 47| (reserved for future use) +| 48| (reserved for future use) +| 49| (reserved for future use) +| 50| (reserved for future use) +| 51| (reserved for future use) +| 52| (reserved for future use) +| 53| (reserved for future use) +| 54| (reserved for future use) +| 55| (reserved for future use) +| 56| Security Alert - Level 1 +| 57| Security Alert - Level 2 +| 57| Security Alert - Level 3 +| 59| (reserved for future use) +| 60| (reserved for future use) +| 61| (reserved for future use) +| 62| (reserved for future use) +| 63| (reserved for future use) +| 64| Distress Area: Vessel disabled and adrift +| 65| Distress Area: Vessel sinking +| 66| Distress Area: Vessel abandoning ship +| 67| Distress Area: Vessel requests medical assistance +| 68| Distress Area: Vessel flooding +| 69| Distress Area: Vessel fire/explosion +| 70| Distress Area: Vessel grounding +| 71| Distress Area: Vessel collision +| 72| Distress Area: Vessel listing/capsizing +| 73| Distress Area: Vessel under assault +| 74| Distress Area: Person overboard +| 75| Distress Area: SAR area +| 76| Distress Area: Pollution response area +| 77| (reserved for future use) +| 78| (reserved for future use) +| 79| (reserved for future use) +| 80| Instruction: Contact VTS at this point/juncture +| 81| Instruction: Contact Port Administration at this point/juncture +| 82| Instruction: Do not proceed beyond this point/juncture +| 83| Instruction: Await instructions prior to proceeding beyond this point/juncture +| 84| Proceed to this location – await instructions +| 85| Clearance granted – proceed to berth +| 86| (reserved for future use) +| 87| (reserved for future use) +| 88| Information: Pilot boarding position +| 89| Information: Icebreaker waiting area +| 90| Information: Places of refuge +| 91| Information: Position of icebreakers +| 92| Information: Location of response units +| 93| VTS active target +| 94| Rogue or suspicious vessel +| 95| Vessel requesting non-distress assistance +| 96| Chart Feature: Sunken vessel +| 97| Chart Feature: Submerged object +| 98| Chart Feature: Semi-submerged object +| 99| Chart Feature: Shoal area +|100| Chart Feature: Shoal area due north +|101| Chart Feature: Shoal area due east +|102| Chart Feature: Shoal area due south +|103| Chart Feature: Shoal area due west +|104| Chart Feature: Channel obstruction +|105| Chart Feature: Reduced vertical clearance +|106| Chart Feature: Bridge closed +|107| Chart Feature: Bridge partially open +|108| Chart Feature: Bridge fully open +|109| (reserved for future use) +|110| (reserved for future use) +|111| (reserved for future use) +|112| Report from ship: Icing info +|113| (reserved for future use) +|114| Report from ship: Miscellaneous information – define in associated text field +|115| (reserved for future use) +|116| (reserved for future use) +|117| (reserved for future use) +|118| (reserved for future use) +|119| (reserved for future use) +|120| Route: Recommended route +|121| Route: Alternative route +|122| Route: Recommended route through ice +|123| (reserved for future use) +|124| (reserved for future use) +|125| Other – Define in associated text field +|126| Cancellation – cancel area as identified by Message Linkage ID +|127| Undefined (default) +|============================================================================== + +Subarea types are as follows: + +[frame="topbot",options="header"] +|============================================================================== +| 0 | Circle or point +| 1 | Rectangle +| 2 | Sector +| 3 | Polyline +| 4 | Polygon +| 5 | Associated text +| 6-7 | Reserved +|============================================================================== + +Subarea payload layouts are as follows: + +.Circle or Point +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member/Type |T|Units +|0-2 | 3 |Shape of area |shape |e|Constant: 0 +|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions + 1 = meters (default) +|5-29 | 25 |Longitude |lon |I3|Longitude of center point, + Unit = minutes * 0.001, + 181000 = N/A (default). +|30-53 | 24 |Latitude |lat |I3|Latitude of center point, + Unit = minutes * 0.001, + 91000 = N/A (default). +|54-56 | 3 |Precision |precision |u|Decimal places of precision + (defaults to 4) +|57-68 | 12 |Radius |radius |u|Radius of area + 0 = point (default), + else 1-4095 * 10^scale m +|69-86 | 18 |Spare | |x|Not used +|============================================================================== + +.Rectangle +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member/Type |T|Units +|0-2 | 3 |Shape of area |shape |e|Constant: 1 +|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions + 1 = meters (default) +|5-29 | 25 |Longitude |lon |I3|Longitude of SW corner + Unit = minutes * 0.001, + 181000 = N/A (default). +|30-53 | 24 |Latitude |lat |I3|Latitude of SW corner + Unit = minutes * 0.001, + 91000 = N/A (default). +|54-56 | 3 |Precision |precision |u|Decimal places of precision + (defaults to 4) +|57-64 | 8 |E dimension |east |u|Box dimension east + 0 = N/S line (default), + else 1-255 * 10^scale m +|65-72 | 8 |N dimension |north |u|Box dimension north + 0 = E/W line (default), + else 1-255 * 10^scale m +|73-81 | 9 |Orientation |orientation |u|Degrees clockwise from true N, + 0 = no rotation (default), + else 1-359, + 360-511 reserved. +|82-86 | 5 |Spare | |x|Not used +|============================================================================== + +.Sector +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member/Type |T|Units +|0-2 | 3 |Shape of area |shape |e|Constant: 2 +|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions + 1 = meters (default) +|5-29 | 25 |Longitude |lon |I3|Longitude of center point, + Unit = minutes * 0.001, + 181000 = N/A (default). +|30-53 | 24 |Latitude |lat |I3|Latitude of center point, + Unit = minutes * 0.001, + 91000 = N/A (default). +|54-56 | 3 |Precision |precision |u|Decimal places of precision + (defaults to 4) +|57-68 | 12 |Radius |radius |u|Radius of area + 0 = point (default), + else 1-4095 * 10^scale m +|69-77 | 9 |Left boundary |left |u|Degrees clockwise from true N, + 0 = no rotation (default), + else 1-359, + 360-511 reserved. +|78-86 | 9 |Right boundary |right |u|Degrees clockwise from true N, + 0 = no rotation (default), + else 1-359, + 360-511 reserved. +|============================================================================== + +.Polyline +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member/Type |T|Units +|0-2 | 3 |Shape of area |shape |e|Constant: 3 +|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions + 1 = meters (default) +|5 | | |waypoints |a4|Waypoints array +|0-9 |10 |Bearing |bearing |u|True bearing in half-degree + steps from previous waypoint; + 720 = N/A (default). +|10-19 |10 |Distance |distance |u|Distance from prev. waypoint, + 0 = no point (default), + else 1-1023 * 10^scale m +|============================================================================== + +The last two fields are repeated 4 times; the final 2 bits of 87 are +unused. A polyline must be preceded by either (a) a circle, in which +case the first bearing is from the center, or (b) a polyline, in which +case the first bearing is from the implied last point. + +.Polygon +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member/Type |T|Units +|0-2 | 3 |Shape of area |shape |e|Constant: 4 +|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions + 1 = meters (default) +|5 | | |vertices |a4|Vertices array +|0-9 |10 |Bearing |bearing |u|True bearing in half-degree + steps from previous vertex; + 720 = N/A (default). +|10-19 |10 |Distance |distance |u|Distance from prev. vertex, +|============================================================================== + +The last two fields are repeated 4 times; the final 2 bits of 87 are +unused. A polygon must be preceded by a circle; the first bearing is +from the circle center, which is treated as the zero vertex. There is +an implied boundary from the last polygon vertex to the zero vertex. + +.Associated text +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member/Type |T|Units +|0-2 | 3 |Shape of area |shape |e|Constant: 5 +|3-86 |84 |Text |text |t|14 chars of packed 6-bit. +|============================================================================== + +==== IMO289 Dangerous Cargo Indication ==== + +See the IMO236 variant for the meaning of this message. + +A message 6 subtype. DAC = 001 FID = 25. Variable length: 117-576 bits. +This is the <> version; there is an earlier <> version +with a different layout, deprecated in <>. + +//: Type 6(1/25) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default) + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 25 +|88-89 | 2 |Unit of Quantity |unit |e|See "Cargo Unit Codes" +|90-99 | 10 |Amount of Cargo |amount |u|Unsigned integer + 0 = N/A (default) + 0 = N/A (default) +|100 | | |cargos |a28|Cargo types array +|0-3 | 4 |Cargo code |code |e|See "Cargo Codes" +|4-16 | 13 |Cargo subtype |subtype |u|Unsigned integer + 0 = N/A (default) +|============================================================================== + +The last two fields may repeat to describe up to 28 subcargos. The count +of repetitions must be computed from the message payload length. + +For cargo unit codes, see the description of the IMO236 variant of +this message. + +.Cargo Codes +[width="50%",frame="topbot",options="header"] +|=================================== +|Code |Code under which cargo is carried +|0 |Not available (default) +|1 |IMDG Code (in packed form) +|2 |IGC code +|3 |BC Code (from 1.1.2011 IMSBC) +|4 |MARPOL Annex I List of oils (Appendix 1) +|5 |MARPOL Annex II IBC Code +|6 |Regional use +|7-15 |Reserved for future use +|=================================== + +The subtype field may be interpreted as an IMDG class or division code +(if the cargotype is 1 = IMDG code) or as a UN number (if the +cargotype is 2 = IGC code) or as a pair of BC class and IMDG class (if +the cargotype is 3 = BC code) or as a MARPOL Annex I code (if +the cargotype is 4 = MARPOL Annex I) or as a MARPOL Annex II code (if +the cargotype is 5 = MARPOL Annex II). + +.Dangerous Cargo Indication: MARPOL Annex I list of oils +[width="50%",frame="topbot",options="header"] +|=================================== +|0 | N/A (default) +|1 | asphalt solutions +|2 | oils +|3 | distillates +|4 | gas oil +|5 | gasoline blending stocks +|6 | gasoline +|7 | jet fuels +|8 | naphtha +|9-15 | reserved for future use +|=================================== + +.Dangerous Cargo Indication: MARPOL Annex II list of oils +[width="50%",frame="topbot",options="header"] +|=================================== +|0 | N/A (default) +|1 | Category X +|2 | Category Y +|3 | Category Z +|4 | Other substances +|5-7 | reserved for future use +|=================================== + +==== IMO289 Route Information (addressed) ==== + +The content of this message is a time and a list of waypoints describing a +course. It has a broadcast equivalent that is a message 8 subtype. + +A message 6 subtype. DAC = 001 FID = 28. Variable length: 204-1029 bits. + +//: Type 6(1/28) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmission (default), + 1 = retransmitted. +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 28 +|88-97 | 10 |Message Linkage ID|linkage |u|Unsigned integer +|98-100 | 3 |Sender Class |sender |u|0 = ship (default), + 1 = authority, + 27 = reserved for future use +|101-105 | 5 |Route Type |rtype |e|See "Route Type Codes" +|106-109 | 4 |Start month (UTC) |month |u|1-12, 0=N/A (default) +|110-114 | 5 |Start day (UTC) |day |u|1-31, 0=N/A (default) +|115-119 | 5 |Start hour (UTC) |hour |u|0-23, 24=N/A (default) +|120-125 | 6 |Start minute (UTC)|minute |u|0-59, 60=N/A (default) +|126-143 | 18 |Duration |duration |u|Minutes from start time, + 0 = cancel route, + 262,143 = N/A (default), +|144-148 | 5 | |waycount |u|Waypoint count (1-16), + Values 17-31 are not used. +|149 | | |waypoints |a^16|Waypoint array +|0-27 | 28 |Longitude |lon |I4|Minutes * 0.0001, + 181000 = N/A (default), + E positive, W negative. +|28-54 | 27 |Latitude |lat |I4|Minutes * 0.0001, + 91000 = N/A (default), + N positive, S negative. +|============================================================================== + +The final pair of fields in the table above is a waypoint. The message may +end with 1 to 16 waypoints. + +.Route Type Codes +[width="50%",frame="topbot",options="header"] +|=================================== +|0 |Undefined (default) +|1 |Mandatory +|2 |Recommended +|3 |Alternative +|4 |Recommended route through ice +|5 |Ship route plan +|6-30 |Reserved for future usage +|31 |Cancel route identified by message linkage +|=================================== + +==== IMO289 Text description (addressed) ==== + +This message may be used to attach a text description to another message with +a Message Linkage ID matching this one. It is intended that the combination +of MMSI and Message Linkage ID should be unique. + +A message 6 subtype. DAC = 001 FID = 30. Variable length: 104-1028 bits. + +Intended to be used to associate a text annotation with another message +via the Message Linkage ID field. + +//: Type 6(1/30) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit |u|0 = no retransmit (default), + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 30 +|88-97 | 10 |Message Linkage ID|linkage |u|Unsigned integer +|98-? | 6-930 |Description |description|t|String +|============================================================================== + +There is an equivalent subtype of message 8 that is a broadcast description. + +==== Tidal Window (IMO289) ==== + +See the <> version of this message for intended meaning. + +A message 6 subtype. DAC = 001 FID = 32. Variable length: 186-362 bits. +This is the <> version; there is an <> version with +different bit widths for the latitude and longitude fields. + +//: Type 6(1/32) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default), + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 001 +|82-87 | 6 |FID |fid |u|FID = 32 +|88-91 | 4 |Month |month |u|1-12; 0 = N/A (default) +|92-96 | 5 |Day |day |u|1-31; 0 = N/A (default) +|97 | | |tidals |a3|Tidal information array +|0-24 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, + 181000 = N/A (default), + E positive, W negative. +|25-48 | 24 |Latitude |lat |I3|Unit = minutes * 0.001. + 91000 = N/A (default), + N positive, S negative. +|49-53 | 5 |From UTC Hour |from_hour |u|0-23, 24 = N/A (default) +|54-59 | 6 |From UTC Minute |from_min |u|0-59, 60 = N/A (default) +|60-64 | 5 |To UTC Hour |to_hour |u|0-23, 24 = N/A (default) +|65-70 | 6 |To UTC Minute |to_min |u|0-59, 60 = N/A (default) +|71-79 | 9 |Current Dir. Predicted |cdir |u|0-359 true bearing, + 360 = N/A (default). +|80-87 | 8 |Current Speed Predicted|cspeed |U1|0-250, units of 0.1 knots, + 251 = speed >= 25.1 knots, + 255 = N/A (default). +|============================================================================= + +The group of fields from longitude on may repeat twice more to convey up to +three points of tidal information. + +==== ETA at lock/bridge/terminal (Inland AIS) ==== + +A message 6 subtype. DAC = 200 FID = 21. Fixed length, 248 bits. + +Should be used by inland vessels only, to send an ETA report to a +lock, bridge or terminal in order to apply for a time slot in resource +planning. + +An acknowledgement by Inland AIS message 22 should be received within +15 minutes. Otherwise, the Inland AIS message 21 should be repeated +once. + +//: Type 6(200/21) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70 | 1 |Retransmit flag |retransmit|u|0 = no retransmit (default), + 1 = retransmitted +|71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 200 +|82-87 | 6 |FID |fid |u|FID = 21 +|88-99 | 12 |UN Country Code |country |t|2 six-bit characters +|100-117 | 18 |UN/LOCODE |locode |t|3 six-bit characters +|118-147 | 30 |Fairway section |section |t|5 six-bit characters +|148-177 | 30 |Terminal code |terminal |t|5 six-bit characters +|178-207 | 30 |Fairway hectometre |hectometre|t|5 six-bit characters +|208-211 | 4 |ETA month |month |u|1-12, 0=N/A (default) +|212-216 | 5 |ETA day |day |u|1-31, 0=N/A (default) +|217-221 | 5 |ETA hour |hour |u|0-23, 24=N/A (default) +|222-227 | 6 |ETA minute |minute |u|0-59, 60=N/A (default) +|228-230 | 3 |Assisting Tugs |tugs |u|0-6, 7 = unknown (default) +|231-242 | 12 |Air Draught |airdraught|u|0-4000 * 0.01m, + 0 = Unknown (default) +|243-247 | 5 |Spare | |x|Not used +|============================================================================== + +<> says of the Destination MMSI field "a virtual MMSI number +should be used for each country, each national AIS network should +route messages addressed to other countries using this virtual MMSI +number". + +OPEN-QUESTION: <> does not specify whether ETA time is UTC +or local. + +==== RTA at lock/bridge/terminal (Inland AIS) ==== + +A message 6 subtype. DAC = 200 FID = 22. Fixed length, 232 bits. + +This message should be sent by base stations only, to assign a RTA at +a lock, bridge or terminal to a certain vessel in response to the +preceding ETA request. + +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit|u|0 = no retransmit (default), + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 200 +|82-87 | 6 |FID |fid |u|FID = 21 +|88-99 | 12 |UN Country Code |country |t|2 six-bit characters +|100-117 | 18 |UN/LOCODE |locode |t|3 six-bit characters +|118-147 | 30 |Fairway section |section |t|5 six-bit characters +|148-177 | 30 |Terminal code |terminal |t|5 six-bit characters +|178-207 | 30 |Fairway hectometre |hectometre|t|5 six-bit characters +|208-211 | 4 |RTA month |month |u|1-12, 0=N/A (default) +|212-216 | 5 |RTA day |day |u|1-31, 0=N/A (default) +|217-221 | 5 |RTA hour |hour |u|0-23, 24=N/A (default) +|222-227 | 6 |RTA minute |minute |u|0-59, 60=N/A (default) +|228-229 | 2 |Status |status |e|See "Status Codes" below +|230-231 | 2 |Spare | |x|Not used +|============================================================================== + +OPEN-QUESTION: <> does not specify whether ETA time is UTC +or local. + +OPEN-QUESTION: No default is specified for the Status field. + +.Lock/Bridge/Terminal status codes +[frame="topbot",options="header"] +|============================================================================== +| 0 | Operational +| 1 | Limited operation +| 2 | Out of order +| 3 | N/A +|============================================================================== + +==== Number of persons on board (Inland AIS) ==== + +This message should be sent by inland vessels only, to inform about +the number of persons (passengers, crew, and shipboard personnel) on +board. + +A message 6 subtype. DAC = 200 FID = 55. Fixed length, 168 bits. + +//: Type 6(200/55) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit|u|0 = no retransmit (default), + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 200 +|82-87 | 6 |FID |fid |u|FID = 55 +|88-95 | 8 |# crew on board |crew |u|Unsigned integer + 0-254, + 255 = Unknown (default) +|96-108 | 13 |# passengers on board|passengers|u|Unsigned integer + 0-8190, + 8191 = Unknown (default) +|109-116 | 8 |# personnel on board |personnel |u|Unsigned integer + 0-254, + 255 = Unknown (default) +|117-167 | 51 |Spare | |x|Not used +|============================================================================== + +==== AtoN monitoring data (GLA) ==== + +This message provides AtoN (Aid to navigation) monitoring data for the General +Lighthouse Authorities (GLA), which consists of Trinity House (England & +Wales), Northern Lighthouse Board (Scotland) and the Commissioners of Irish +Lights (Ireland). It is described in <>. + +A message 6 subtype. DAC = 235 or 250 FID = 10. Fixed length: 136 bits. + +DAC and FI are user configurable, DAC=235/FI=10 is used in UK, DAC=250/FI=10 +in the Republic Of Ireland. + +The interval between the transmissions of these messages will be synchronized +with message 21, although not necessarily at the same reporting rate. If +Message 21 is not used at a particular site, then the reporting interval +should be selected to minimize the power requirement of the transponder, +whilst still providing enough data to enable meaningful diagnostic analysis. + +OPEN-QUESTION: <> lists a broadcast (type 8) variant of this +message, but without indicating how the Destination MMSI field is to +be set or interpreted. Robust implementations should accept and +process this variant. + +//: Type 6(235-250:10) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-70 | 1 |Retransmit flag |retransmit |u|0 = no retransmit (default), + 1 = retransmitted +|71-71 | 1 |Spare | |x|Not used +|72-81 | 10 |DAC |dac |u|DAC = 235 or 250 +|82-87 | 6 |FID |fid |u|FID = 10 +|88-97 | 10 |Analogue |ana_int |u|0.05-36V, 0.05V step + Supply voltage to AIS Unit + 0 = Not Used +|98-107 | 10 |Analogue (ext. #1)|ana_ext1 |u|0.05-36V, 0.05V step + 0 = Not Used +|108-117 | 10 |Analogue (ext. #2)|ana_ext2 |u|0.05-36V, 0.05V step + 0 = Not Used +|118-119 | 2 |RACON status |racon |u|00 = no RACON installed + 01 = RACON not monitored + 10 = RACON operational + 11 = RACON ERROR +|120-121 | 2 |Light status |light |u|00 = no light or no monitoring + 01 = Light ON + 10 = Light OFF + 11 = Light ERROR +|122 | 1 |Health |health |b|0 = Good Health, 1 = Alarm +|123-130 | 8 |Status (external) |stat_ext |u|7 Digital Input 0=Off, 1=On + : + : + 0 Digital Input 0=Off, 1=On +|131-131 | 1 |Position status |off_pos |b|0=On position, 1=Off position +|132-135 | 4 |Spare | |x|Not used +|============================================================================== + +=== Type 7: Binary Acknowledge === + +Message type 7 is a receipt acknowledgement to the senders of a +previous messages of type 6. Total length varies between 72 and 168 +bits by 32-bit increments, depending on the number of destination +MMSIs included. + +//: Type 7 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 7 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-69 | 30 |MMSI number 1 |mmsi1 |u|9 decimal digits +|70-71 | 2 |Sequence for MMSI 1 |mmsiseq1 |u|Not used +|72-101 | 30 |MMSI number 2 |mmsi2 |u|9 decimal digits +|102-103 | 2 |Sequence for MMSI 2 |mmsiseq2 |u|Not used +|104-133 | 30 |MMSI number 3 |mmsi3 |u|9 decimal digits +|134-135 | 2 |Sequence for MMSI 3 |mmsiseq3 |u|Not used +|136-165 | 30 |MMSI number 4 |mmsi4 |u|9 decimal digits +|166-167 | 2 |Sequence for MMSI 4 |mmsiseq4 |u|Not used +|============================================================================== + +Use of the MMSI sequence fields was introduced in ITU-1371-5 to +indicate the sequence number of the Type 6 to which this responds. +In earlier versions these were spare fields. + +=== Type 8: Binary Broadcast Message === + +Message type 8 is a broadcast message with unspecified binary payload. +The St. Lawrence Seaway AIS system, the USG PAWSS system, and the Port +Authority of London use this payload for local extension +messages. <> and <> describe payload use as +international extension messages. This type is variable in length up +to a maximum of 1008 bits (up to 5 AIVDM sentence payloads). + +//: Type 8 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |Designated Area Code |dac |u|Unsigned integer +|50-55 | 6 |Functional ID |fid |u|Unsigned integer +|56 |952 |Data |data |d|Binary data, + May be shorter than 952 bits. +|============================================================================== + +Interpretation of the binary payload is controlled by DAC/FID as in +message type 6. The following is a non-exhaustive list of standardized +DAC-FID pairs in use for type 8: + +[frame="topbot",options="header"] +|============================================================================== +| DAC |FID | Sub | Source | Status | Description +| 1 | 11 | | <> | Deprecated/In Use | Meteorological/Hydrological Data +| 1 | 13 | | <> | Deprecated | Fairway closed +| 1 | 15 | | <> | Deprecated | Extended ship and voyage +| 1 | 17 | | <> | In use | VTS-Generated/Synthetic targets +| 1 | 19 | | <> | Standard | Marine traffic signals +| 1 | 21 | | <> | Standard | Weather observation from ship +| 1 | 22 | | <> | In use | Area notice (broadcast) +| 1 | 24 | | <> | Standard | Extended ship and voyage +| 1 | 26 | | <> | Standard | Environmental +| 1 | 27 | | <> | Standard | Route info broadcast +| 1 | 29 | | <> | Standard | Text description broadcast +| 1 | 31 | | <> | In use | Meteorological and Hydrological +| 200 | 10 | | <> | Standard | Ship static and voyage related data +| 200 | 23 | | <> | Standard | EMMA warning report +| 200 | 24 | | <> | Standard | Water levels +| 200 | 40 | | <> | Standard | Signal status +| 316/366 | 1 | 2 | <> | In use | Wind +| 316/366 | 1 | 1 | <> | In use | Weather station +| 316/366 | 1 | 3 | <> | In use | Water level +| 316/366 | 1 | 6 | <> | In use | Water flow +| 316/366 | 2 | 1 | <> | In use | Lockage Order +| 316/366 | 2 | 2 | <> | In use | Estimated Lock Times +| 316/366 | 32 | 1 | <> | In use | Seaway Version Message +| 366 | 1 | 4 | <> | In use | PAWS Hydro / Current +| 366 | 1 | 6 | <> | In use | PAWS Hydro / Salinity Temp +| 366 | 1 | 3 | <> | In use | PAWS Vessel Procession Order +|============================================================================== + +DAC/FID pairs are assigned separately per message type. For St. Lawrence +Seaway messages, the DAC may be 316 (Canada) or 366 (U.S.) depending +on the transmitter location. + +Note that the apparent presence of one of these DAC/FID pairs does +not guarantee that the message is structured. Decoders should +perform range validation on the structured fields and interpret the +message as unstructured if any check fails. Actual false matches with +DAC/FID = 200/10 have been observed in the wild. + +DAC/FID pairs 1/23, 1/28, and 1/30 have addressed versions described +under type 6. + +FID types 11-15 are being phased out and are not to be used after 1 +Jan 2013. The deprecated IMO236 1/11 has a different binary layout from +the IMO289 1/31. FID type 17 is in use; there is a proposed +update for it in <>. + +Breakdowns of Message 8 subtypes from <> follow. + +==== Meteorological and Hydrological Data (IMO236) ==== + +A message 8 subtype. DAC = 001 FID = 11. Fixed length, 352 bits. +This is in use and described in <>, but has been deprecated by +<<289>> in favor of a message with the same title but FID = 31 and a +different binary layout. <> specifies a maximum interval between +broadcast of this message of 12 minutes. + +//: Type 8(1/11) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |u|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 11 +|56-79 | 24 |Latitude |lat |I3|Unit = minutes * 0.001, + 0x7FFFFF = N/A (default), + E positive, W negative. +|80-104 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, + 0xFFFFFF = N/A (default), + N positive, S negative. +|105-109 | 5 |Day (UTC) |day |u|1-31, 31=N/A (default) +|110-114 | 5 |Hour (UTC) |hour |u|0-23, 31=N/A (default) +|115-120 | 6 |Minute (UTC) |minute |u|0-59, 63=N/A (default) +|121-127 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed, knots, + 127 = N/A (default). +|128-134 | 7 |Gust Speed |wgust |u|10-min max wind speed, knots, + 127 = N/A (default). +|135-143 | 9 |Wind Direction |wdir |u|0-359, degrees from true north + 511 = N/A (default) +|144-152 | 9 |Wind Gust Direction|wgustdir |u|0-359, degrees fom true north + 511 = N/A (default) +|153-163 | 11 |Air Temperature |temperature |u|Dry bulb temp: 0.1 deg C + -60.0 to +60.0, + 2047 = N/A (default), +|164-170 | 7 |Relative Humidity |humidity |u|0-100%, units of 1%, + 127 = N/A (default). +|171-180 | 10 |Dew Point |dewpoint |u|-20.0 to +50.0: 0.1 deg C, + 1023 = N/A (default), +|181-189 | 9 |Air Pressure |pressure |u|800-1200hPa: units 1hPa, + 511 = N/A (default). +|190-191 | 2 |Pressure Tendency |pressuretend|e|0 = steady, + 1 = decreasing, + 2 = increasing, + 3 - N/A (default). +|192-199 | 8 |Horiz. Visibility |visibility |U1|0-25.0, units of 0.1nm + 255 = N/A (default) +|200-208 | 9 |Water Level |waterlevel |I1|-10.0 to +30.0 in 0.1m, + 511 = N/A (default). +|209-210 | 2 |Water Level Trend |leveltrend |e|0 = steady, + 1 = decreasing, + 2 = increasing, + 3 - N/A (default). +|211-218 | 8 |Surface Current Speed |cspeed |U1|0.0-25.0 knots: units 0.1 knot +|219-227 | 9 |Surface Current Direction |cdir |u|0-359: deg from true north, + 511 = N/A (default) +|228-235 | 8 |Current Speed #2 |cspeed2 |U1|0.0-25.0 in units of 0.1 knot, + 255 = N/A (default). +|236-244 | 9 |Current Direction #2 |cdir2 |u|0-359: deg. fom true north, + 511 = N/A (default) +|245-249 | 5 |Measurement Depth #2 |cdepth2 |U1|0-30m down: units 0.1m, + 31 = N/A (default). +|250-257 | 8 |Current Speed #3 |cspeed3 |U1|0.0-25.0: units of 0.1 knot, + 255 = N/A (default). +|258-266 | 9 |Current Direction #3 |cdir3 |u|0-359: degrees fom true north, + 511 = N/A (default). +|267-271 | 5 |Measurement Depth #3 |cdepth3 |U1|0-30m down: units 0.1m, + 31 = N/A (default). +|272-279 | 8 |Wave height |waveheight|U1|0-25m: units of 0.1m, + 255 = N/A (default). +|280-285 | 6 |Wave period |waveperiod|u|Seconds 0-60: + 63 = N/A (default). +|286-294 | 9 |Wave direction |wavedir |u|0-359: deg. fom true north, + 511 = N/A (default). +|295-302 | 8 |Swell height |swellheight|U1|0-25m: units of 0.1m + 255 = N/A (default). +|303-308 | 6 |Swell period |swellperiod|u|Seconds 0-60: + 63 = N/A (default). +|309-317 | 9 |Swell direction |swelldir |u|0-359: deg. fom true north, + 511 = N/A (default). +|318-321 | 4 |Sea state |seastate |e|See "Beaufort Scale" +|322-331 | 10 |Water Temperature |watertemp |U1|-10.0 to 50.0: units 0.1 C, + 1023 = N/A (default). +|332-334 | 3 |Precipitation |preciptype |e|See "Precipitation Types" +|335-343 | 9 |Salinity |salinity |U1|0.0-50.0%: units 0.1%, + 511 = N/A (default) +|344-345 | 2 |Ice |ice |e| 0 = No + 1 = Yes + 2 = (reserved for future use) + 3 = not available = default +|346-351 | 6 |Spare | |x|Not used +|============================================================================== + +<> says "If there is no data available, default value to be +transmitted is the highest available binary value for that particular +data field.", the above table reflects that. The day, hour and minute +have to be considered not available when all three are set to their +individual "N/A" value. For the latitude and the longitude, the +highest positive value is used, as the highest available binary value +for a signed integer is -1, which would forbid the -0.001/-0.001 +position. The replacement FID=31 message has different default values +that remove any ambiguities. + +<> gives the length of this message as 352, but lists only 336 +payload bits. + +Water level is deviation from local chart datum and includes tide. + +The waveheight field is labeled as "Significant" in <>, +for whatever that means. + +The seastate field has a note in <> reading "(manual input?)"? + +WMO 306 Code table 4.201 specifies the following precipitation type values: + +.Precipitation Types +[width="50%",frame="topbot",options="header"] +|=================================== +|Code |Precipitation Type +|0 |Reserved +|1 |Rain +|2 |Thunderstorm +|3 |Freezing rain +|4 |Mixed/ice +|5 |Snow +|6 |Reserved +|7 |N/A (default) +|=================================== + +.Beaufort Scale +[width="50%",frame="topbot",options="header"] +|=========================================================================== +|Scale|Description | Sea Conditions +|0 |Calm |Flat. +|1 |Light air |Ripples without crests. +|2 |Light breeze |Small wavelets. +| Crests of glassy appearance, not breaking. +|3 |Gentle breeze |Large wavelets. +| Crests begin to break; scattered whitecaps. +|4 |Moderate breeze|Small waves. +|5 |Fresh breeze |Moderate (1.2 m) longer waves. Some foam and spray. +|6 |Strong breeze |Large waves with foam crests and some spray. +|7 |High wind |Sea heaps up and foam begins to streak. +|8 |Gale |Moderately high waves with breaking crests +| forming spindrift. Streaks of foam. +|9 |Strong gale |High waves (6-7 m) with dense foam. +| Wave crests start to roll over. Considerable spray. +|10 |Storm |Very high waves. The sea surface is white and there +| is considerable tumbling. Visibility is reduced. +|11 |Violent storm |Exceptionally high waves. +|12 |Hurricane force|Huge waves. Air filled with foam and spray. Sea +| completely white with driving spray. Visibility +| greatly reduced. +|13 | |N/A (default) +|14-15| |Reserved +|=========================================================================== + +==== Fairway Closed ==== + +This message should be broadcast from shore stations to inform ships, +in particular to give guidance to large vessels about temporary closed +fairways or sections in ports. + +A message 8 subtype. DAC = 001 FID = 13. Fixed length, 472 bits. +Described in <> but deprecated by <>. + +//: Type 8(1/13) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 13 +|56-175 |120 |Reason For Closing |reason |t|20 6-bit characters +|176-295 |120 |Location Of Closing From|closefrom|t|20 6-bit characters +|296-415 |120 |Location of Closing To |closeto |t|20 6-bit characters +|416-425 | 10 |Radius extension |radius |u|0-1000, 10001 = N/A (default) +|426-427 | 2 |Unit of extension |extunit |u|0=m, 1=km, 2=nm, 3=cables +|428-432 | 5 |From day (UTC) |fday |u|1-31, 0=N/A (default) +|433-436 | 4 |From month (UTC) |fmonth |u|1-12, 0=N/A (default) +|437-441 | 5 |From hour (UTC) |fhour |u|0-23, 24=N/A (default) +|442-447 | 6 |From minute (UTC) |fminute |u|0-59, 60=N/A (default) +|448-452 | 5 |To day (UTC) |tday |u|1-31, 0=N/A (default) +|453-456 | 4 |To month (UTC) |tmonth |u|1-12, 0=N/A (default) +|457-461 | 5 |To hour (UTC) |thour |u|0-23, 24=N/A (default) +|462-467 | 6 |To minute (UTC) |tminute |u|0-59, 60=N/A (default) +|468-471 | 4 |Spare | |x|Not used +|============================================================================== + +No default is specified for the radius field in the standard. + +==== IMO236 Extended Ship Static and Voyage Related Data ==== + +This message should be used by a ship to report the height over keel. + +A message 8 subtype. DAC = 001 FID = 15 in <>. Fixed length, 72 bits. +Deprecated in <>. + +//: Type 8(1/15) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 15 +|55-66 | 11 |Air Draught |airdraught|u|Height in meters, + 0 = N/A (default), + 2047 = >= 2047 m, +|67-71 | 5 |Spare | |x|Not used +|============================================================================== + +==== VTS-Generated/Synthetic targets ==== + +A message 8 subtype. DAC = 001 FID = 17. Variable length: 176-536 +bits. This message is laid out identically in <> and +<>. In <> it is titled "Pseudo-AIS Targets". + +//: Type 8(1/17) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 17 +|56 | | |targets |a4|Synthetic targets array +|0-1 | 2 |Identifier type |idtype |e|0 = id is the MMSI number, + 1 = id is the IMO number, + 2 = id is the call sign, + 3 = Other (default). +|2-43 | 42 |Target identifier |id |u|Target ID data. +|44-47 | 4 |Spare | |x|Not used +|48-71 | 24 |Latitude |lat |I3|Minutes * 0.001, + 91000 = N/A (default), + N positive, S negative. +|72-96 | 25 |Longitude |lon |I3|Minutes * 0.001, + 181000 = N/A (default), + E positive, W negative. +|97-105 | 9 |Course Over Ground |course |u|0-359 deg from true north, + 360 = N/A (default). +|106-111 | 6 |Time Stamp |second |u|Second of UTC timestamp. +|112-121 | 10 |Speed Over Ground |speed |u|0-254 in knots, 255 = N/A. +|============================================================================== + +The interpretation of the target identifier field depends on the +preceding type key. For 0 and 1 it is a big-endian unsigned binary +integer (as shown above). For type 2 and 3 it is 6-bit ASCII text. An +unknown target is expressed by type 3 and the string "@@@@@@@". + +OPEN-QUESTION: <> says: "When MMSI or IMO number is used, the +least significant bit should equal bit zero of the Target Identifier." +It is unclear how "bit zero" is to be interpreted, but it is not +possible to reconcile interpreting it as the leading bit of the field +with AIS big-endian encoding. Settling this awaits live testing. + +The trailing eight fields may be repeated up to 3 times (for a total of 1 to 4 +field groups) to represent up to 4 targets. + +==== IMO289 Marine Traffic Signal ==== + +This message provides information on a signal station and status of +the control signal at the entrance of a harbour or channel where the +shipping direction controlled so that the traffic flow be kept in +order. + +A message 8 subtype described in <>. DAC = 001 FID = 19. Fixed +length: 360 bits. + +//: Type 8(1/19) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |u|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 19 +|56-65 | 10 |Message Linkage ID |linkage |u|Unsigned integer +|66-185 | 120 |Name of Signal Station|station |t|20 6-bit chars +|186-210 | 25 |Longitude |lon |I3|Unit = minutes * 0.001 + 181000 = N/A (default) + E positive, W negative. +|211-234 | 24 |Latitude |lat |I3|Unit = minutes * 0.001 + 91000 = N/A (default) + N positive, S negative. +|235-236 | 2 |Status of Signal |status |u|0=N/A (default + 1 = In regular service + 2 = Irregular service + 3 = Reserved for future use +|237-241 | 5 |Signal In Service |signal |e|See "Marine Traffic Signals" +|242-246 | 5 |UTC hour |hour |u|0-23, 24=N/A (default) +|247-252 | 6 |UTC minute |minute |u|0-59, 60=N/A (default) +|253-257 | 5 |Expected Next Signal |nextsignal|e|See "Marine Traffic Signals" +|258-359 | 102 |Spare | |x|Not used +|============================================================================== + +.Marine Traffic Signals +[width="50%",frame="topbot",options="header"] +|=========================================================================== +|Code |Position Fix Type +| 0 |N/A (default) +| 1 |IALA port traffic signal 1: Serious emergency – all vessels to stop +| or divert according to instructions. +| 2 |IALA port traffic signal 2: Vessels shall not proceed. +| 3 |IALA port traffic signal 3: Vessels may proceed. One way traffic. +| 4 |IALA port traffic signal 4: Vessels may proceed. Two way traffic. +| 5 |IALA port traffic signal 5: A vessel may proceed only when it has +| received specific orders to do so. +| 6 |IALA port traffic signal 2a: Vessels shall not proceed, except that +| vessels which navigate outside the main channel need not comply with +| the main message. +| 7 |IALA port traffic signal 5a: A vessel may proceed only when it has +| received specific orders to do so; except that vessels which navigate +| outside the main channel need not comply with the main message. +| 8 |Japan Traffic Signal - I = "in-bound" only acceptable. +| 9 |Japan Traffic Signal - O = "out-bound" only acceptable. +| 10 |Japan Traffic Signal - F = both "in- and out-bound" acceptable. +| 11 |Japan Traffic Signal - XI = Code will shift to "I" in due time. +| 12 |Japan Traffic Signal - XO = Code will shift to "O" in due time. +| 13 |Japan Traffic Signal - X = Vessels shall not proceed, except a vessel +| which receives the direction from the competent authority. +|14-31|Reserved +|=========================================================================== + +==== IMO289 Weather observation report from ship ==== + +There are two variants of this message. They are distinguished by bit 56, +the WMO bit. Field layouts after that bit vary depending on it. + +A message 8 subtype described in <>. DAC = 001 FID = 21. Fixed +length: 360 bits. + +//: Type 8(1/21) +.Weather observation report from ship: Non-WMO variant +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 21 +|56-56 | 1 |Variant |wmo |b|Constant: 0 in this variant +|57-176 | 120 |Location |location |t|20 6-bit characters +|177-201 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, + 181000 = N/A (default), + E positive, W negative. +|202-225 | 24 |Latitude |lat |I3|Unit = minutes * 0.001, + 91000 = N/A (default), + N positive, S negative. +|226-230 | 5 |UTC Day |day |u|1-31, 0=N/A (default) +|231-235 | 5 |UTC hour |hour |u|0-23, 24=N/A (default) +|236-241 | 6 |UTC minute |minute |u|0-59, 60=N/A (default) +|242-245 | 4 |Present Weather |weather |u|wmocode: 0-15 +|246-246 | 1 |Visibility Limit |vislimit |b|See below +|247-253 | 7 |Horiz. Visibility |visibility |U1|0.0-12.6nm, units = nm*0.1, + 127 = N/A (default). +|254-260 | 7 |Relative Humidity |humidity |u|0-100%: units of 1%, + 127 = N/A (default). +|261-267 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed knots, + 127 = N/A (default). +|268-276 | 9 |Wind Direction |wdir |u|0-359, deg. fom true north, + 360 = N/A (default). +|277-285 | 9 |Air Pressure |pressure |u|800-1200hPa: units 1hPa, + 402 = pressure >= 1201 hPa, + 403 - N/A (default), + else add 400 to value, +|286-289 | 4 |Pressure Tendency |pressuretend|u|WMO FM13 code +|290-300 | 11 |Air Temperature |airtemp |I1|Dry bulb temp: units 0.1C, + -60.0 to +60.0, + -1024 = N/A (default). +|301-310 | 10 |Water Temperature |watertemp |I1|-10.0 to 50.0 in 0.1 C, + 601 = N/A (default), + else -10C after scaling. +|311-316 | 6 |Wave period |waveperiod |u|Seconds: 0-60, + 63 = N/A (default). +|317-324 | 8 |Wave height |waveheight |U1|0-25m in units of 0.1m, + 255 = N/A (default). +|325-333 | 9 |Wave direction |wavedir |u|0-359: deg. fom true north, + 360 = N/A (default). +|334-341 | 8 |Swell height |swellheight |U1|0-25m: units 0.1m, + 255 = N/A (default) +|342-350 | 9 |Swell direction |swelldir |u|0-359: deg, fom true north, + 360 = N/A (default). +|351-356 | 6 |Swell period |swellperiod |u|Seconds: 0-60, + 63 = N/A (default). +|357-359 | 3 |Spare | |x|Not used +|============================================================================== + +The vislimit bit, when on, indicates that the maximum range of the +visibility equipment was reached and the visibility reading shall be +regarded as > x.x NM. + +The standard (<>) does not list the WMO FM13 codes. +The following table applies: + +.Weather observation report from ship: WMO Code 45501 +[width="50%",frame="topbot",options="header"] +|=========================================================================== +|Code |Precipitation Type +| 0 |Clear (no clouds at any level) +| 1 |Cloudy +| 2 |Rain +| 3 |Fog +| 4 |Snow +| 5 |Typhoon/hurricane +| 6 |Monsoon +| 7 |Thunderstorm +| 8 |N/A (default) +| 9-15|Reserved for future use +|=========================================================================== + +.Weather observation report from ship: WMO variant +[frame="topbot",options="header"] +|============================================================================== +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 21 +|56-56 | 1 |Variant |wmo |u|Constant: 1 in this variant +|57-72 | 16 |Longitude |lon |I3|Unsigned: minutes * 0.01, + E positive, W negative, + Lon = (value / 100) – 180, + 65536 = N/A (default). +|73-87 | 15 |Latitude |lat |I3|Unsigned: minutes * 0.01, + N positive, S negative, + Lat = (value / 100) – 90, + 32767 = N/A (default). +|88-91 | 4 |UTC Month |month |u|1-12, 15=N/A (default) +|92-97 | 6 |UTC Day |day |u|1-31, 63=N/A (default) +|98-102 | 5 |UTC hour |hour |u|0-23, 31=N/A (default) +|103-105 | 3 |UTC minute |minute |u|0-50, 7=N/A (default), + Minute = (value * 10). +|106-112 | 7 |Course Over Ground |course |u|0-359, unit = 1 degree, + average over last 10 minutes. +|113-117 | 5 |Speed Over Ground |speed |U1|0-14.5m/s: + SOG = (value * 0.5) for 0-29, + 30 = 15 m/s and more, + average over last 10 minutes. + 31 = N/A (default) +|118-124 | 7 |Heading of the ship |heading |u|5-360: units of 5 degrees, + HDT = (value * 5) for 1-72, + average over last 10 minutes. + 127 = N/A (default) +|125-135 | 11 |Pressure at sea level |pressure|U1|90-1100 hPa: + P = (value/10)+900 for 0-2000 +|136-145 | 10 |Pressure Change |pdelta |U1|-50-+50hPa: units of 0.1hPa, + d = (value/10)-50 for 0-100, + averaged over last 3 hours. + 1023 = N/A (default) +|146-149 | 4 |Pressure Tendency |ptend |u|WMO BUFR table 010063: + Averaged over last 3 hours, + 0-8, 15 = N/A. +|150-156 | 7 |True Wind Direction |twinddir|u|005-360: deg: + average over last 10 minutes, + dir = (value*5), value 1-72, + 0 = calm, + 127 = N/A (default). +|157-164 | 8 |True Wind Speed |twindspeed|u|0-127 m/s: + average over last 10 mins, + speed = value * 0.5, + 255 = N/A (default). +|165-171 | 7 |Relative Wind Direction|rwinddir |u|005-360 deg: + average over last 10 mins, + dir = (value*5) for 1-72, + 0 = calm, + 127 = N/A (default). +|172-179 | 8 |Relative Wind Speed |rwindspeed|U1|0-127 m/s: + average over last 10 mins, + speed = val*0.5 for 0-254, + 255 = N/A (default). +|180-187 | 8 |Maximum Gust Speed |mgustspeed|U1|0-127 m/s: + speed = val*0.5 for 0-254, + 255 = N/A (default), +|188-194 | 7 |Maximum Gust Direction |mgustdir |u|05-360 deg: + dir = (value*5) for 1-72, + 0 = calm, + 127 = N/A (default). +|195-204 | 10 |Air Temperature |airtemp |U1|Dry bulb temp: units 0.1C, + 223-323K (c.-50C - +50C). + T = (val/10)+223 for 0-1000, + 1023 = N/A (default). +|205-211 | 7 |Relative Humidity |humidity |u|0-100%: units of 1%, + 127 = N/A (default). +|212-220 | 9 |Sea Surface Temperature|surftemp |U1|268-318K (c.-5C - +45C): + T = (val/10)+268 for 0-500, + 511 = N/A (default). +|221-226 | 6 |Horiz. Visibility |visibility|U2|0-50000m, + Vis = (val**2)*13.073 for 0-62, + 63 = N/A (default). +|227-235 | 9 |Present Weather |weather |u|BUFR table 020003: + Codes 0-510, + 511 = N/A (default). +|236-240 | 5 |Past Weather 1 |pweather1 |u|BUFR table 020005: + Codes 0-30, + 31 = N/A (default). +|241-245 | 5 |Past Weather 2 |pweather2 |u|BUFR table 020004: + Codes 0-30, + 31 = N/A (default). +|246-249 | 4 |Total Cloud Cover |totalcloud|u|0-100%: + Cover = val * 10% for 0-10, + 15 = N/A (default.) +|250-253 | 4 |Cloud amount (low) |lowclouda |u|0-14: BUFR table 020011: + 15 = N/A (default). +|254-259 | 6 |Cloud type (low) |lowcloudt |u|0-62: BUFR table 020012: + 63 = N/A (default). +|260-265 | 6 |Cloud type (middle) |midcloudt |u|0-62: BUFR table 020012: + 63 = N/A (default). +|266-271 | 6 |Cloud type (high) |highcloudt|u|0-62: BUFR table 020012: + 63 = N/A (default). +|272-278 | 7 |Height of cloud base |cloudbase |U2|0-2500m: + h = (value**2)*.0.16 for 0-125, + 126 = more than 2500m, + 127 = N/A (default). +|279-283 | 5 |Period of Wind Waves |wwperiod |u|0-30s: + 31 = N/A (default). +|284-289 | 6 |Height of Wind Waves |wwheight |u|Height in meters: 0-30, + h = (value * 0.5) for 0-60, + 63 = N/A (default). +|290-295 | 6 |First Swell Direction |swelldir1 |u|10-360 deg: + dir = (value*10) for 1-36, + 0 = calm, + 63 = N/A (default). +|296-300 | 5 |First Swell Period |swperiod1 |u|Period in seconds: 0-30, + 31 = N/A (default). +|301-306 | 6 |First Swell Height |swheight1 |U1|Height in meters: 0-30, + h = (value * 0.5) for 0-60, + 63 = N/A (default). +|307-312 | 6 |Second Swell Direction |swelldir2 |u|10-360 deg: + dir = (value*10) for 1-36, + 0 = calm, + 63 = N/A (default). +|313-317 | 5 |Second Swell Period |swperiod2 |u|Period in seconds: 0-30, + 31 = N/A (default). +|318-323 | 6 |Second Swell Height |swheight2 |U1|Height in meters: 0-30, + h = (value * 0.5) for 0-60, + 63 = N/A (default). +|324-330 | 7 |Ice deposit (thickness)|icedeposit|u|Thickness: 0-126cm, + 127 = N/A (default). +|331-333 | 3 |Rate of Ice Accretion |icerate |u|0-6: BUFR table 020032: + 7 = N/A (default). +|334-336 | 3 |Cause of Ice Accretion |icecause |u|0-6: BUFR table 020033: + 7 = N/A (default). +|337-341 | 5 |Sea Ice Concentration |seaice |u|0-30: BUFR table 020034: + 31 = N/A (default). +|342-345 | 4 |Amount and Type of Ice |icetype |u|0-14: BUFR table 020035: + 15 = N/A (default). +|346-350 | 5 |Ice Situation |icestate |u|0-30: BUFR table 020036: + 31 = N/A (default). +|351-355 | 5 |Ice Development |icedevel |u|0-30: BUFR table 020037: + 31 = N/A (default). +|356-359 | 4 |Bearing of Ice Edge |icebearing|u|Bearing: 45-360 deg, + dir = (value*45) for 1-8, + 15 = N/A (default). +|============================================================================== + +The "minute" entry actually only identifies the end of a 10-minute interval. + +In <>, the Latitude formula is given as "Lat = (value / 100) – 9000". +This is incorrect; the decrement needs to be 90 for the range to be -90..+90. + +Swell directions are arrival directions. + +==== IMO289 Area Notice (broadcast) ==== + +This should be used to broadcast time- and location-dependent information about +hazards to navigation. For information-lifetime restrictions and usage +guidance, refer to <>. + +A message 8 subtype. DAC = 001 FID = 22. 196 to 981 bits. There is a +related Message 6 subtype for addressed use. + +The message consists of a fixed-length header of 111 bits, followed by 1 to +10 sub-area indications which are fixed-length records 87 bits long. Here +is the message header format: + +//: Type 8(1/22) +.Area Notice (addressed) message header +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 22 +|56-65 | 10 |Message Linkage ID |linkage |u|Unsigned integer +|66-72 | 7 |Notice Description |notice |u|See table below +|73-76 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) +|77-81 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|82-86 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|87-92 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|93-110 | 18 |Duration |duration |In minutes, + 262143 = N/A (default), + 0 = cancel this notice. +|143 | | |subarea |a10|Subarea array +|0-2 | 2 | |shape |u|Subarea shape +|3-86 | 85 |Subarea Payload |payload |d|Subarea payload +|============================================================================== + +The sub-area indications are as described under the addressed form, +message type 6 with DAC = 1 and FID = 23. + +==== IMO289 Extended Ship Static and Voyage Related Data ==== + +This message should be used by a ship to report the height over keel. + +A message 8 subtype. DAC = 001 FID = 24 in <>. Fixed length, 360 bits. +Replaces a deprecated trial message from <>. + +//: Type 8(1/24) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in CNB +|8-37 | 30 |Source MMSI |mmsi |u|9 digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 24 +|56-65 | 10 |Message Linkage ID |linkage |u|Unsigned integer +|66-78 | 13 |Air Draught |airdraught |u|Unsigned int, in 0.1m + 1-81.9 m. + 0 = N/A (default) + 81.91 = >= 81.91 m +|79-108 | 30 |Last Port Of Call |lastport |t|5 6-bit chars, UN locode +|109-138 | 30 |Next Port Of Call |nextport |t|5 6-bit chars, UN locode +|139-168 | 30 |Second Port Of Call |secondport |t|5 6-bit chars, UN locode +|169-170 | 2 |AIS Class A |ais_state |e|See "SOLAS Status" +|171-172 | 2 |Automatic Tracking Aid |ata_state |e|See "SOLAS Status" +|173-174 | 2 |BNWAS |bnwas_state |e|See "SOLAS Status" +|175-176 | 2 |ECDIS Back-up |ecdisb_state |e|See "SOLAS Status" +|177-178 | 2 |Paper Nautical Chart |chart_state |e|See "SOLAS Status" +|179-180 | 2 |Echo sounder |sounder_state |e|See "SOLAS Status" +|181-182 | 2 |Electronic plotting aid|epaid_state |e|See "SOLAS Status" +|183-184 | 2 |Emergency steering gear|steer_state |e|See "SOLAS Status" +|185-186 | 2 |GNSS |gnss_state |e|See "SOLAS Status" +|187-188 | 2 |Gyro compass |gyro_state |e|See "SOLAS Status" +|189-190 | 2 |LRIT |lrit_state |e|See "SOLAS Status" +|191-192 | 2 |Magnetic compass |magcomp_state |e|See "SOLAS Status" +|193-194 | 2 |NAVTEX |navtex_state |e|See "SOLAS Status" +|195-196 | 2 |Radar (ARPA) |arpa_state |e|See "SOLAS Status" +|197-198 | 2 |Radar (S-band) |sband_state |e|See "SOLAS Status" +|199-200 | 2 |Radar (X-band) |xband_state |e|See "SOLAS Status" +|201-202 | 2 |Radio HF |hfradio_state |e|See "SOLAS Status" +|203-204 | 2 |Radio INMARSAT |inmarsat_state|e|See "SOLAS Status" +|205-206 | 2 |Radio MF |mfradio_state |e|See "SOLAS Status" +|207-208 | 2 |Radio VHF |vhfradio_state|e|See "SOLAS Status" +|209-210 | 2 |Speed Log over ground |grndlog_state |e|See "SOLAS Status" +|211-212 | 2 |Speed Log through water|waterlog_state|e|See "SOLAS Status" +|213-214 | 2 |THD |thd_state |e|See "SOLAS Status" +|215-216 | 2 |Track control system |tcs_state |e|See "SOLAS Status" +|217-218 | 2 |VDR/S-VDR |vdr_state |e|See "SOLAS Status" +|219-220 | 2 |Reserved | |x|Not used +|221-224 | 4 |Ice Class |iceclass |e|See "Ice Class" +|225-242 | 18 |Shaft Horsepower |horsepower |u|Total ship HP: 1hp units, + 262,142 = >= 262,142hp, + 262,143 = N/A (default). +|243-254 | 12 |VHF Working Channel |vhfchan |u|Channel number, + 0 = N/A (default). +|255-296 | 42 |Lloyd's Ship Type |lshiptype |t|7 six-bit characters +|297-314 | 18 |Gross Tonnage |tonnage |u|0-262,141, + 262,142 = >= 262,142hp, + 262,143 = N/A (default). +|315-316 | 2 |Laden or Ballast |lading |e|0 = N/A (default), + 1 = Laden, + 2 = Ballast, + 3 = Not in use. +|317-318 | 2 |Heavy Fuel Oil Bunkered|heavyoil |e|0 = N/A (default), + 1 = No, + 2 = Yes, + 3 = Not in use. +|319-320 | 2 |Light Fuel Oil Bunkered|lightoil |e|0 = N/A (default), + 1 = No, + 2 = Yes, + 3 = Not in use. +|321-322 | 2 |Diesel Oil Bunkered |dieseloil |e|0 = N/A (default), + 1 = No, + 2 = Yes, + 3 = Not in use. +|323-336 | 14 |Total Bunker Oil |totaloil |u|0-16381 in tonnes, + 16382 = >= 16382 tonnes, + 16382 = N/A (default). +|337-349 | 13 |Number of persons |persons |u|0 = N/A (default), + 1-8190, + 8191 = >= 8191. +|350-359 | 10 |Spare | |x|Not used +|============================================================================== + +The special value of 81.91 for air draught is probably a drafting +error in <>, as the scaled field does not have the precision +required to represent it. The actual special value is unknown. + +The 2-bit _state fields describe the operational state of various sorts of +SOLAS-required navigational equipment. GNSS systems may include GPS, Loran-C, or GLONASS. BNWAS is the Bridge Navigational Watch Alarm System. THD is a +Transmitting Heading Device. Paper Nautical Chart state is officially +"ECDIS/Paper Nautical Chart" state in <>. Status codes should be +interpreted according to the following table: + +.SOLAS Status +[width="50%",frame="topbot",options="header"] +|============================================================================= +|Code |Meaning +|0 |Not available or requested (default) +|1 |Equipment operational +|2 |Equipment not operational +|3 |No data (equipment may or may not be on board/or its status is unknown) +|============================================================================= + +.Ice Class +[width="50%",frame="topbot",options="header"] +|============================================================================= +|Code |Meaning +|0 |Not classified +|1 |IACS PC 1 +|2 |IACS PC 2 +|3 |IACS PC 3 +|4 |IACS PC 4 +|5 |IACS PC 5 +|6 |IACS PC 6 / FSICR IA Super / RS Arc5 +|7 |IACS PC 7 / FSICR IA / RS Arc4 +|8 |FSICR IB / RS Ice3 +|9 |FSICR IC / RS Ice2 +|10 |RS Ice1 +|11-14|Reserved for future use +|15 |Not available = default +|============================================================================= + +ACS = International Association of Classification Societies + +PC = Polar Class. For further details, see IACS Req. 2007 Requirements +concerning POLAR CLASS and MSC/Circ.1056 and MEPC/Circ.399 on +Guidelines for ships operating in Arctic ice-covered waters. + +FSICR = Finnish-Swedish Ice Class Rules. For further details, see +Finnish Maritime Administration's Bulletin No.10/10.12.2008 Ice class +regulations 2008 (Finnish-Swedish ice class rules). Note: Authorized +classification society equivalents for the Finnish-Swedish Ice Class +Rules should also be recognized, as issued in the Finnish Maritime +Administration's Bulletin No.4/2.4.2007 (as amended). Both bulletins +can be found at www.fma.fi. + +RS = Russian Maritime Register of Shipping. For further details see +Rules for the classification and construction of seagoing ships, +Edition 2008. + +VHF channel number is encoded according to Recommendation ITU-R M.1084. + +The lshiptype field uses Lloyd's Register STATCODE 5 encoding. + +==== IMO289 Environmental ==== + +A message 8 subtype. DAC = 001 FID = 26. Variable length: 168-1008 bits. + +//: Type 8(1/26) +.Environmental message header +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 26 +|56 | | |reports |a5|Sensor records array +|0-3 | 4 |Sensor Report Type |sensor |u|See table below +|4-8 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|9-13 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|14-19 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|20-26 | 7 |Site ID |site |u|Binary ID of sensor site +|27-111 | 85 |Sensor payload |payload |d|Sensor payload data +|============================================================================== + +The fixed header is followed by 1-5 sensor records, each 112 bits +long. The Sensor Report Type is interpreted as follows, and controls +the interpretation of the sensor payload data. + +.Sensor report types +[frame="topbot",options="header"] +|============================================================================== +| 0 | Site location +| 1 | Station ID +| 2 | Wind +| 3 | Water level +| 4 | Current flow (2D) +| 5 | Current flow (3D) +| 6 | Horizontal current flow +| 7 | Sea state +| 8 | Salinity +| 9 | Weather +| 10| Air gap/Air draft +| 11| (reserved for future use) +|============================================================================== + +Here are the payload types for each variant: + +.Site location payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-27 | 28 |Longitude |lon |I4|As in Common Navigation Block +|28-54 | 27 |Latitude |lat |I4|As in Common Navigation Block +|55-65 | 11 |Altitude |alt |u|Sensor altitude above MSL, + 0-200 in units of 0.1m, + 2001 = 200.1 m or higher, + 2002 = N/A (default), + 2003-2046 reserved. +|66-69 | 4 |Sensor owner |owner |e|See "Sensor Owner Codes" +|70-72 | 3 |Data timeout |timeout |e|See "Data Timeout Codes" +|73-84 | 12 |Spare | |x|Not used +|============================================================================== + +.Sensor Owner Codes +[frame="topbot",options="header"] +|============================================================================== +| 0 | Unknown (default) +| 1 | Hydrographic office +| 2 | Inland waterway authority +| 3 | Coastal directorate +| 4 | Meteorological service +| 5 | Port Authority +| 6 | Coast guard +| 7-13 | (reserved for future use) +| 14 | (reserved for regional use) +|============================================================================== + +.Data Timeout Codes +[frame="topbot",options="header"] +|============================================================================== +| 0 | No time period (default) +| 1 | 10 minutes +| 2 | 1 hour +| 3 | 6 hours +| 4 | 12 hours +| 5 | 24 hours +| 6-7 | (reserved for future use) +|============================================================================== + +.Station ID payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +| 0 | 84 |Name |name |t|14 chars of six-bit ASCII. +| 84 | 1 |Spare | |x|Not used +|============================================================================== + +.Wind report payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-6 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed, + 0-120 in 1-knot units, + 121 = 121 knots or greater, + 122 = N/A (default), + 123-126 = reserved. +|7-13 | 7 |Wind Gust |wgust |u|10-min max wind speed, + 0-120 in 1-knot units, + 121 = 121 knots or greater, + 122 = N/A (default), + 123-126 = reserved. +|14-22 | 9 |Wind Direction |wdir |u|0-359, degrees fom true north + >=360 = N/A (default) +|23-31 | 9 |Wind Gust Direction|wgustdir |u|0-359, degrees fom true north + >=360 = N/A (default) +|32-34 | 3 |Sensor Description |sensortype |e|See "Sensor Types" +|35-41 | 7 |Forecast Wind Speed|fwspeed |u|Predicted average wind speed, + 0-120 in 1-knot units, + 121 = 121 knots or greater, + 122 = N/A (default), + 123-126 = reserved. +|42-48 | 7 |Forecast Wind Gust |fwgust |u|Predicted max wind speed, + 0-120 in 1-knot units, + 121 = 121 knots or greater, + 122 = N/A (default), + 123-126 = reserved. +|49-57 | 9 |Forecast Wind Direction|fwdir |u|0-359, degrees fom true north + >=360 = N/A (default) +|58-62 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|63-67 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|68-73 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|74-81 | 8 |Duration |duration |u|Forecast duration in minutes, + 255 = N/A (default), + 0 = cancel forecast. +|82-84 | 3 |Spare | |x|Not used +|============================================================================== + +The timestamp group is intended as a valid time of forecast. + +.Sensor Types +[frame="topbot",options="header"] +|============================================================================== +| 0 | No data (default) +| 1 | Raw real time +| 2 | Real time with quality control +| 3 | Predicted (based on historical statistics) +| 4 | Forecast (predicted, refined with real-time information) +| 5 | Nowcast (a continuous forecast) +| 6 | (reserved for future use) +| 7 | Sensor not available +|============================================================================== + +.Water level report payload +[frame="topbot",options="header"] +|============================================================================== +|0-0 | 1 |Water Level Type |absolute |b|False if relative to + reference datum. +|1-16 | 16 |Water Level |level |i|In 0.001 meter steps, + -327.67 to 327.67, + -32767 = -327.67m or less, + 32767 = 327.67m or more, + -32768 = N/A (default). +|17-18 | 2 |Water Level Trend |leveltrend |u| 0 = increasing, + 1 = decreasing, + 2 = steady, + 3 = N/A (default). +|19-23 | 5 |Vertical Reference Datum |datum |u|See table below +|24-26 | 3 |Sensor Description |sensortype |e|See "Sensor Types" +|27-27 | 1 |Forecast Water Level Type|absolute |b|False if relative to + reference datum. +|28-43 | 16 |Forecast Water Level |level |i|In 0.001 meter steps, + -327.67 to 327.67, + -32767 = -327.67m or less, + 32767 = 327.67m or more, + -32768 = N/A (default). +|44-48 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|49-53 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|54-59 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|60-67 | 8 |Duration |duration |u|Forecast duration in minutes, + 255 = N/A (default), + 0 = cancel forecast. +|68-84 | 17 |Spare | |x|Not used +|============================================================================== + +IMO289 says water level is in 0.1m steps, but this is incompatible with the +two digits of precision in the range. + +The timestamp group is intended as a valid time of forecast. + +.Vertical Reference Datum +[frame="topbot",options="header"] +|============================================================================== +| 0 | Mean Lower Low Water (MLLW) +| 1 | International Great Lakes Datum (IGLD-85) +| 2 | Local river datum +| 3 | Station Datum (STND) +| 4 | Mean Higher High Water (MHHW) +| 5 | Mean High Water (MHW) +| 6 | Mean Sea Level (MSL) +| 7 | Mean Low Water (MLW) +| 8 | National Geodetic Vertical Datum (NGVD-29) +| 9 | North American Vertical Datum (NAVD-88) +| 10 | World Geodetic System (WGS-84) +| 11 | Lowest Astronomical Tide (LAT) +| 12 | pool +| 13 | gauge +| 14 | Unknown/not available (default) +| 15-30| Reserved for future use +|============================================================================== + +.Current flow (2D) report payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-7 | 8 |Current Speed #1 |cspeed1 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|8-16 | 9 |Current Direction #1 |cdir1 |u|0-359: deg from true north, + >=360 = N/A (default). +|17-25 | 9 |Measurement Depth #1 |cdepth1 |u|0-360m down: units 1m, + 361 = 361m or greater, + 362 = N/A (default), + 363-511 (reserved). +|26-33 | 8 |Current Speed #2 |cspeed2 |U1|0.0-24.5 knots, + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|34-42 | 9 |Current Direction #2 |cdir2 |u|0-359: deg. fom true north, + >=360 = N/A (default) +|43-51 | 9 |Measurement Depth #2 |cdepth2 |u|0-360m down: units 1m, + 361 = 361m or greater, + 362 = N/A (default), + 363-511 (reserved). +|52-59 | 8 |Current Speed #3 |cspeed3 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|60-68 | 9 |Current Direction #3 |cdir3 |u|0-359: degrees fom true north, + >=360 = N/A (default). +|69-77 | 9 |Measurement Depth #3 |cdepth3 |u|0-360m down: units 1m, + 361 = 361m or greater, + 362 = N/A (default), + 363-511 (reserved). +|78-80 | 3 |Sensor Description |sensortype|e|See "Sensor Types" +|81-84 | 4 |Spare | |x|Not used +|============================================================================== + +.Current flow (3D) payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-7 | 8 |Current Vector component North (u) #1|cnorth1 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|8-15 | 8 |Current Vector component East (v) #1|ceast1 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|16-23 | 8 |Current Vector component Up (z) #1 |cup1 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|24-32 | 9 |Measurement Depth #1 |cdepth1 |u|0-360m down: + units 1m, + 361 = 361m or greater, + 362 = N/A (default), + 363-511 (reserved). +|33-40 | 8 |Current Vector component North (u) #2|cnorth2 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|41-48 | 8 |Current Vector component East (v) #2|ceast2 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|49-56 | 8 |Current Vector component Up (z) #2 |cup2 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|57-65 | 9 |Measurement Depth #2 |cdepth2 |u|0-360m down: + units 1m, + 361 = 361m or greater, + 362 = N/A (default), + 363-511 (reserved). +|66-68 | 3 |Sensor Description |sensortype|e|See "Sensor Types" +|69-84 | 16 |Spare | |x|Not used +|============================================================================== + +.Horizontal current report payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-8 | 9 |Current Bearing #1 |bearing1 |u|0-359: deg from true north, + >=360 = N/A (default). +|9-15 | 7 |Current Distance #1 |distance1 |u|0-120m: + 121 = 121m or greater, + 122 = N/A (default), + 123-127 (reserved). +|16-23 | 8 |Current Speed #1 |speed1 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|24-32 | 9 |Current Direction #1 |direction1|u|0-359: deg from true north, + >=360 = N/A (default). +|33-41 | 9 |Measurement Depth #1 |depth1 |u|0-360m down: units 1m, + 361 = 361m or greater, + 362 = N/A (default), + 363-511 (reserved). +|42-50 | 9 |Current Bearing #2 |bearing1 |u|0-359: deg from true north, + >=360 = N/A (default). +|51-57 | 7 |Current Distance #2 |distance1 |u|0-120m: + 121 = 121m or greater, + 122 = N/A (default), + 123-127 (reserved). +|58-65 | 8 |Current Speed #2 |speed1 |U1|0.0-24.5 knots: + units 0.1 knots, + 246 = speed >= 24.6 knots, + 247 = N/A (default), + 248-255 (reserved). +|66-74 | 9 |Current Direction #2 |direction1|u|0-359: deg from true north, + >=360 = N/A (default). +|75-83 | 9 |Measurement Depth #2 |depth1 |u|0-360m down: units 1m, + 361 = 361m or greater, + 362 = N/A (default), + 363-511 (reserved). +|84-84 | 1 |Spare | |x|Not used +|============================================================================== + +.Sea state report payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-7 | 8 |Swell Height |swheight |U1|Units 0.1m: 0.0-24.5m, + 246 = height >= 24,6m, + 247 = N/A (default), + 248-255 reserved, + else h = (value * 0.5). +|8-13 | 6 |Swell Period |swperiod |u|Period in seconds: + 0-60, + 61 = N/A (default), + 62-63 (reserved). +|14-22 | 9 |Swell Direction |swelldir |u|0-359 deg: + 0-359 true bearing, + 360 = N/A (default), + 361-511 reserved, +|23-26 | 4 |Sea State |seastate |u|Beaufort scale: 0-12 + >= 13 = N/A (default) +|27-29 | 3 |Swell Sensor Description |swelltype |e|See "Sensor Types" +|30-39 | 10 |Water Temperature |watertemp |U1|-10.0 to 50.0: + units 0.1 C, + >=601 = N/A (default). + 602-1023 reserved, + else -10.0m after scaling. +|40-46 | 7 |Water Temperature Depth |distance1 |U1|0.0-12.0m: 0.1m units, + 121 = 12.1m or greater, + 122 = N/A (default), + 123-126 (reserved). +|47-49 | 3 |Depth Sensor Description |depthtype |e|See "Sensor Types" + +|50-57 | 8 |Wave Height |waveheight|U1|Height 0.0-24.5m: + units 0.1m, + 246 = height >= 24.6m, + 247 N/A (default), + 248-255 reserved. +|58-63 | 6 |Wave Period |waveperiod|u|0-60: units of seconds, + 61 = N/A (default), + 62-63 reserved. +|64-72 | 9 |Wave Direction |wavedir |u|0-359: true bearing, + 360 = N/A (default), + 361-511 reserved. +|73-75 | 3 |Wave Sensor Description |wavetype |e|See "Sensor Types" +|76-84 | 9 |Salinity |salinity |U1|0.0-50.0%: + units of 0.1% + 501 = salinity >= 50.1% + 502 = data N/A (default) + 503 - sensor N/A, + 504-511 reserved. +|============================================================================== + +The standard does not fix the meaning of a water temperature depth of 127. + +.Salinity report payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-9 | 10 |Water Temperature |watertemp |U1|-10.0 to 50.0: + units 0.1 C, + >=601 = N/A (default). + 602-1023 reserved, + else -10.0m after scaling. +|10-19 | 10 |Conductivity |conductivity |U1|In Siemens/m, 0.0-7.0, + 0.1 S/m steps, + 701 = not less than 7.01, + 702 = data N/A, + 703 = sensor N/A (default), + 704-1023 (reserved). +|20-35 | 16 |Water Pressure |pressure |U1|Water pressure: 0.0-6000.0, + 0.1 decibar steps, + 60001 = pressure >= 6000.1, + 60002 = data N/A, + 60003 = sensor N/A (default), + 60004-65536 reserved. +|36-44 | 9 |Salinity |salinity |U1|0.0-50.0%: + units of 0.1% + 501 = salinity >= 50.1% + 502 = data N/A (default) + 503 - sensor N/A, + 504-511 reserved. +|45-46 | 2 |Salinity Type |salinitytype|e|0 = measured, + 1 = calculated using PSS-78, + 2 = calculated using other method, + 3 = reserved. +|47-49 | 3 |Sensor Description |sensortype |e|See "Sensor Types" +|50-84 | 35 |Spare | |x|Not used +|============================================================================== + +No default is specified for salinity type. + +.Weather report payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-10 | 11 |Air Temperature |temperature|i|Dry bulb temp: 0.1 deg C + -60.0 to +60.0, + -1024 = data N/A (default), + 601-1023 reserved. +|11-13 | 3 |Temp. Sensor Type |sensortype |e|See "Sensor Types" +|14-15 | 2 |Precipitation Type |preciptype |e|0 = rain, + 1 = rain and snow, + 2 = rain and snow, + 3 = other. +|16-23 | 8 |Horiz. Visibility |visibility |U1|Units of 0.1 nautical miles, + 0.0-24.0, + 241 = visibility >= 24.1nm, + 242 = data N/A, + 243 = sensor N/A (default), + 244-255 reserved. +|24-33 | 10 |Dew Point |dewpoint |i|-20.0 to +50.0: 0.1 deg C, + 501 = N/A (default), + 502-511 reserved, + -511--201 reserved. +|34-36 | 3 |Dewpoint Sensor Type|dewtype |e|See "Sensor Types". + + + +|37-45 | 9 |Air Pressure |pressure |u|0 = pressure <= 800hpA, + 1-401 = 800-1200hPa, + 402 = pressure >= 1201 hPa, + 403 - data N/A (default), + 404-511 reserved. +|46-47 | 2 |Pressure Tendency |pressuretend |e|0 = steady, + 1 = decreasing, + 2 = increasing, + 3 - N/A (default). +|48-50 | 3 |Pressure Sensor Type|pressuretype|e|See "Sensor Types" +|51-59 | 9 |Salinity |salinity |U1|0.0-50.0%: + units of 0.1% + 501 = salinity >= 50.1% + 502 = data N/A (default) + 503 - sensor N/A, + 504-511 reserved. +|60-84 | 25 |Spare | |x|Not used +|============================================================================== + +The standard does not specify how to code 'Precipitation Type' when +there is none. + +.Air Gap/Air Draft report payload +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-12 | 13 |Air Draught |airdraught |U1|1-81.9m in 0.1m steps, + 8191 = distance >= 81.91m, + 0 = N/A (default). +|13-25 | 13 |Air Gap |airgap |U1|1-81.9m in 0.1m steps, + 8191 = distance >= 81.91m, + 0 = N/A (default). +|26-27 | 2 |Air Gap Trend |gaptrend |e|0 = steady, + 1 = rising, + 2 = falling, + 3 = N/A (default). +|28-40 | 13 |Forecast Air Gap |fairgap |U1|1-81.9m in 0.1m steps, + 8191 = distance >= 81.91m, + 0 = N/A (default). +|41-45 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|46-50 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|51-56 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|57-84 | 28 |Spare | |x|Not used +|============================================================================== + +Air draught is the vertical distance measured from the ship's +waterline to the highest point on the ship. Air gap is the vertical +distance measured from the surface of the water to the sensor. + +The timestamp is for the forecast air gap. + +==== IMO289 Route Information (broadcast) ==== + +The content of this message is a time and a list of waypoints describing a +course. It has an addressed equivalent that is a message 6 subtype. + +A message 8 subtype. DAC = 001 FID = 27. Variable length: 172-997 bits. + +//: Type 8(1/27) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 27 +|56-65 | 10 |Message Linkage ID|linkage |u|Unsigned integer +|66-68 | 3 |Sender Class |sender |u|0 = ship (default), 1 = authority, + 27 = reserved for future use. +|69-73 | 5 |Route Type |rtype |e|See below +|74-77 | 4 |Start month |month |u|1-12, 0=N/A (default) +|78-82 | 5 |Start day |day |u|1-31, 0=N/A (default) +|83-87 | 5 |Start hour |hour |u|0-23, 24=N/A (default) +|88-93 | 6 |Start minute |minute |u|0-59, 60=N/A (default) +|94-111 | 18 |Duration |duration |u|Minutes from start time, + 0 = cancel route, + 262,143 = not available (default). +|112-116 | 5 |Waypoint count |waycount |u|1-16, values 17-31 are not used. +|117 | | |waypoints|a^16|Waypoint array +|0-27 | 28 |Longitude |lon |I4|Unit = minutes * 0.0001, + 181000 = N/A (default), + E positive, W negative. +|28-54 | 27 |Latitude |lat |I4|Unit = minutes * 0.001, + 91000 = N/A (default), + N positive, S negative. +|============================================================================== + +The final pair of fields in the table above is a waypoint. The message may +end with 1 to 16 waypoints. + +For interpretation of the Route Type field, see the table under the "Route +Information (addressed)" message (DAC=1, FID=28). + +==== IMO289 Text description (broadcast) ==== + +A message 8 subtype. DAC = 001 FID = 29. Variable length: 72-1032 bits. + +Intended to be used to associate a text annotation with another message +via the Message Linkage ID field. + +//: Type 8(1/29) +[frame="topbot",options="header"] +|============================================================================= +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 29 +|56-65 | 10 |Message Linkage ID|linkage |u|Unsigned integer +|66-? | 6-966 |Description |description|t|String +|============================================================================== + +There is an equivalent subtype of message 6 that is an addressed description. + +==== Meteorological and Hydrological Data (IMO289) === + +A message 8 subtype. DAC = 001 FID = 31. Fixed length, 360 bits. +Supersedes an <> message with the same title but FID = 11 and +a different binary layout. The exact differences are: (a) The +addition of the Position Accuracy field, (b) water level has 12 bits +of precision rather than 9 (units of centimeters rather than +decimeters), and (c) end padding changes from 6 to 10 bits. + +//: Type 8(1/31) +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |DAC |dac |u|DAC = 001 +|50-55 | 6 |FID |fid |u|FID = 31 +|56-80 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, + E positive, We negative, + 181000 = N/A (default). +|81-104 | 24 |Latitude |lat |I3|Unit = minutes * 0.001, + N positive, S negative, + 91000 = N/A (default). +|105-105 | 1 |Fix quality |accuracy |b|As in Common Navigation Block +|106-110 | 5 |Day |day |u|1-31, 0=N/A (default) +|111-115 | 5 |Hour |hour |u|0-23, 24=N/A (default) +|116-121 | 6 |Minute |minute |u|0-59, 60=N/A (default) +|122-128 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed: knots, + 126 = wind >= 126 knots, + 127 = N/A (default). +|129-135 | 7 |Gust Speed |wgust |u|10-min max wind speed: knots, + 126 = wind >= 126 knots, + 127 = N/A (default). +|136-144 | 9 |Wind Direction |wdir |u|0-359, true bearing, + 360 = N/A (default). +|145-153 | 9 |Wind Gust Direction|wgustdir |u|0-359, true bearing, + 360 = N/A (default). +|154-164 | 11 |Air Temperature |airtemp |I1|Dry bulb temp: units 0.1C, + -60.0 to +60.0, + -1024 = N/A (default). +|165-171 | 7 |Relative Humidity |humidity |u|0-100%: units of 1%, + 101 = N/A (default). +|172-181 | 10 |Dew Point |dewpoint |I1|-20.0 to +50.0: units 0.1C, + 501 = N/A (default). +|182-190 | 9 |Air Pressure |pressure |u|800-1200hPa, 1hPa, + 0 = pressure <= 799hPa, + 402 = pressure >= 1201 hPa, + 511 = N/A (default). +|191-192 | 2 |Pressure Tendency |pressuretend|e|0 = steady, + 1 = decreasing, + 2 = increasing, + 3 = N/A (default). +|193-193 | 7 |Max. visibility |visgreater |b|Visibility greater than. +|194-200 | 8 |Horiz. Visibility |visibility |U1|Units are 0.1 nautical miles, + 127 = N/A (default). +|201-212 | 12 |Water Level |waterlevel |I2|-10.0 to +30.0 in 0.01m, + -10.0m after scaling, + 4001 = N/A (default). +|213-214 | 2 |Water Level Trend |leveltrend |e|0 = steady, + 1 = decreasing, + 2 = increasing, + 3 = N/A (default). +|215-222 | 8 |Surface Current Speed |cspeed |U1|0.0-25.0: units 0.1 knot, + 251 = speed >= 25.1 knots, + 255 = N/A (default). +|223-231 | 9 |Surface Current Direction |cdir |u|0-359: deg. fom true north, + 360 = N/A (default). +|232-239 | 8 |Current Speed #2 |cspeed2 |U1|0.0-25.0 knots: + units 0.1 knot, + 251 = speed >= 25.1 knots, + 255 = N/A (default). +|240-248 | 9 |Current Direction #2 |cdir2 |u|0-359: true bearing, + 360 = N/A (default). +|249-253 | 5 |Measurement Depth #2 |cdepth2 |U1|0-30m down: units 0.1m, + 31 = N/A (default). +|254-261 | 8 |Current Speed #3 |cspeed3 |U1|0.0-25.0 knots: units 0.1 knot, + 251 = speed >= 25.1 knots, + 255 = N/A (default). +|262-270 | 9 |Current Direction #3 |cdir3 |u|0-359: true bearing, + 360 = N/A (default). +|271-275 | 5 |Measurement Depth #3 |cdepth3 |u|0-30m down: units 0.1m, + 31 = N/A (default). +|276-283 | 8 |Wave Height |waveheight|U1|Height 0-25m: units 0.1m, + 251 = height >= 25.1m, + 255 = N/A (default). +|284-289 | 6 |Wave Period |waveperiod|u|Seconds, 0-60, units 1s, + 63 = N/A (default). +|290-298 | 9 |Wave Direction |wavedir |u|0-359: true bearing, + 360 = N/A (default). +|299-306 | 8 |Swell Height |swellheight|U1|0-25m: units 0.1m, + 251 = height >= 25.1m, + 255 = N/A (default). +|307-312 | 6 |Swell Period |swellperiod|u|0-60, units 1s + 360 = N/A (default) +|313-321 | 9 |Swell Direction |swelldir |u|0-359: true bearing, + 360 = N/A (default) +|322-325 | 4 |Sea State |seastate |e|See "Beaufort scale" +|326-335 | 10 |Water Temperature |watertemp |I1|-10.0 to 50.0 C: + units 0.1 deg, + 501 = N/A (default) +|336-338 | 3 |Precipitation |preciptype |e|See "Precipitation type" +|339-347 | 9 |Salinity |salinity |U1|0.0-50.0%: units of 0.1% + 501 = salinity >= 50.1% + 510 = N/A (default) + 511 = sensor not available +|348-349 | 2 |Ice |ice |u| 0 = No + 1 = Yes + 2 = (reserved for future use) + 3 = not available = default +|350-359 | 10 |Spare | |x|Not used +|============================================================================== + +Precipitation types and Beaufort scale are as for the <> version. + +==== Inland ship static and voyage related data (Inland AIS) ==== + +A message 8 subtype. DAC = 200 FID = 10. Fixed length, 168 bits. + +This message should be used by inland vessels only to broadcast ship +static and voyage related data in addition to message 5. The message +should be sent as soon as possible (from the AIS point of view) after +message 5. + +//: Type 8(200/10) +[frame="topbot",options="header"] +|=============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |Designated Area Code |dac |u|Constant: 200 +|50-55 | 6 |Functional ID |fid |u|Constant: 10 +|56-103 | 48 |European Vessel ID |vin |t|8 six-bit characters +|104-116 | 13 |Length of ship |length |u|1-8000 * 0.1m, default 0 +|117-126 | 10 |Beam of ship |beam |u|1-1000 * 0.1m, default 0 +|127-140 | 14 |Ship/combination type |shiptype |e|ERI Classification +|141-143 | 3 |Hazardous cargo |hazard |e|See "Hazard Codes" below +|144-154 | 11 |Draught |draught |u|1-200 * 0.01m, default 0 +|155-156 | 2 |Loaded/Unloaded |loaded |e|See "Load Status" below +|157-157 | 1 |Speed inf. quality |speed_q |b|0 = low/GNSS (default) + 1 = high +|158-158 | 1 |Course inf. quality |course_q |b|0 = low/GNSS (default) + 1 = high +|159-159 | 1 |Heading inf. quality |heading_q|b|0 = low/GNSS (default) + 1 = high +|160-167 | 8 |Spare | |x|Not used +|============================================================================== + +OPEN-QUESTION: <> is not explicit whether the +"Ship/combination type" field is to contain full ERI codes with range +8000-8370 or ERI SOLAS codes in the range 1-99. The tables below +expand both. Full ERI codes have been observed in the wild. + +.ERI Classification +[frame="topbot",options="header"] +|============================================================================== +|Code | SOLAS | Description +|8000 | 99 | Vessel, type unknown +|8010 | 79 | Motor freighter +|8020 | 89 | Motor tanker +|8021 | 80 | Motor tanker, liquid cargo, type N +|8022 | 80 | Motor tanker, liquid cargo, type C +|8023 | 89 | Motor tanker, dry cargo as if liquid (e.g. cement) +|8030 | 79 | Container vessel +|8040 | 80 | Gas tanker +|8050 | 79 | Motor freighter, tug +|8060 | 89 | Motor tanker, tug +|8070 | 79 | Motor freighter with one or more ships alongside +|8080 | 89 | Motor freighter with tanker +|8090 | 79 | Motor freighter pushing one or more freighters +|8100 | 89 | Motor freighter pushing at least one tank-ship +|8110 | 79 | Tug, freighter +|8120 | 89 | Tug, tanker +|8130 | 31 | Tug freighter, coupled +|8140 | 31 | Tug, freighter/tanker, coupled +|8150 | 99 | Freightbarge +|8160 | 99 | Tankbarge +|8161 | 90 | Tankbarge, liquid cargo, type N +|8162 | 90 | Tankbarge, liquid cargo, type C +|8163 | 99 | Tankbarge, dry cargo as if liquid (e.g. cement) +|8170 | 99 | Freightbarge with containers +|8180 | 90 | Tankbarge, gas +|8210 | 79 | Pushtow, one cargo barge +|8220 | 79 | Pushtow, two cargo barges +|8230 | 79 | Pushtow, three cargo barges +|8240 | 79 | Pushtow, four cargo barges +|8250 | 79 | Pushtow, five cargo barges +|8260 | 79 | Pushtow, six cargo barges +|8270 | 79 | Pushtow, seven cargo barges +|8280 | 79 | Pushtow, eight cargo barges +|8290 | 79 | Pushtow, nine or more barges +|8310 | 80 | Pushtow, one tank/gas barge +|8320 | 80 | Pushtow, two barges at least one tanker or gas barge +|8330 | 80 | Pushtow, three barges at least one tanker or gas barge +|8340 | 80 | Pushtow, four barges at least one tanker or gas barge +|8350 | 80 | Pushtow, five barges at least one tanker or gas barge +|8360 | 80 | Pushtow, six barges at least one tanker or gas barge +|8370 | 80 | Pushtow, seven barges at least one tanker or gas barge +|============================================================================= + +.SOLAS ship type, first digit +[frame="topbot",options="header"] +|============================================================================= +| 3 | Vessel +| 7 | Cargo ship +| 8 | Tanker +| 9 | Other types of ship +|============================================================================= + +.SOLAS ship type, second digit +[frame="topbot",options="header"] +|============================================================================= +| 0 | All ships of this type +| 1 | Towing +| 8 | Tanker +| 9 | No additional information +|============================================================================= + +.Hazard code +[frame="topbot",options="header"] +|============================================================================== +| 0 | 0 blue cones/lights +| 1 | 1 blue cone/light +| 2 | 2 blue cones/lights +| 3 | 3 blue cones/lights +| 4 | 4 B-Flag +| 5 | Unknown (default) +|============================================================================== + +.Load status +[frame="topbot",options="header"] +|============================================================================== +| 0 | N/A (default) +| 1 | Unloaded +| 2 | Loaded +|============================================================================== + +==== EMMA Warning Report (Inland AIS) ==== + +A message 8 subtype. DAC = 200 FID = 23. Fixed length, 256 bits. + +The EMMA warning is sent by base stations to drive shipboard ECDIS +displays of heavy weather conditions. The following message is capable +of transmitting the EMMA data using the AIS channel. It does not +replace the Notices to Skippers warnings. + +//: Type 8(200/23) +[frame="topbot",options="header"] +|=============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |Designated Area Code|dac |u|Constant: 200 +|50-55 | 6 |Functional ID |fid |u|Constant: 23 +|56-63 | 8 |Start Year |start_year |u|1-55, year since 2000 + 0 = N/A (default) +|64-67 | 4 |Start Month |start_month |u|1-12; 0 = N/A (default) +|68-72 | 5 |Start Day |start_day |u|1-31; 0 = N/A (default) +|73-80 | 8 |End Year |end_year |u|1-55, year since 2000 + 0 = N/A (default) +|81-84 | 4 |End Month |end_month |u|1-12; 0 = N/A (default) +|85-89 | 5 |End Day |end_day |u|1-31; 0 = N/A (default) +|90-94 | 5 |Start Hour |start_hour |u|0-23; 24 = N/A (default) +|95-100 | 6 |Start Minute |start_minute|u|0-59; 60 = N/A (default) +|101-105 | 5 |End Hour |end_hour |u|0-23; 24 = N/A (default) +|106-111 | 6 |End Minute |end_minute |u|0-59; 60 = N/A (default) +|112-139 | 28 |Start Longitude |start_lon |I4|Minutes/10000 (as in CNB) +|140-166 | 27 |Start Latitude |start_lat |I4|Minutes/10000 (as in CNB) +|167-194 | 28 |End Longitude |end_lon |I4|Minutes/10000 (as in CNB) +|195-221 | 27 |End Latitude |end_lat |I4|Minutes/10000 (as in CNB) +|222-225 | 4 |Type |type |e|See "EMMA Type Codes" below +|226-234 | 9 |Min value |min |i|Signed Integer, see below +|235-243 | 9 |Max value |max |i|Signed Integer, see below +|244-245 | 2 |Classification |intensity |e|1 = Slight, + 2 = Medium, + 3 = Strong +|246-249 | 4 |Wind Direction |wind |e|See "EMMA Winds" below +|250-255 | 6 |Spare | |x|Not used +|=============================================================================== + +OPEN-QUESTION: <> is not explicit about the interpretation of +the longitude and latitude fields; these semantics are assumed here +from 28 and 27-bit fields in other messages. + +<> specifies an 8-bit format with 9th leading sign bit for the +min and max fields. Values 0-253 are interpreted as integer data, +modified by the leading sign bit. The values +254 and -254 are +interpreted as "greater that +253" and "less than -253" respectively. +Both values +255 and -255 are interpreted as "unknown" (default). + +OPEN-QUESTION: What are the semantics of the min and max values? To +what parameters do they apply? + +OPEN-QUESTION: <> does not specify whether start and end times +are UTC or local. + +.EMMA Type Codes +[frame="topbot",options="header"] +|============================== +| 0 | NA | Not Available +| 1 | WI | Wind +| 2 | RA | Rain +| 3 | SN | Snow and ice +| 4 | TH | Thunderstorm +| 5 | FO | Fog +| 6 | LT | Low temperature +| 7 | HT | High temperature +| 8 | FL | Flood +| 9 | FI | Forest Fire +|============================== + +.EMMA Winds +[frame="topbot",options="header"] +|============================== +| 1 | N | North +| 2 | NE | North East +| 3 | E | East +| 4 | SE | South East +| 5 | S | South +| 6 | SW | South West +| 7 | W | West +| 8 | NW | North West +|============================== + +==== Water Levels (Inland AIS) ==== + +A message 6 subtype. DAC = 200 FID = 24. Fixed length, 168 bits. + +This message should be used to inform skippers about actual water +levels in their area. It is additional short-term information to the +water levels distributed via Notices to Skippers. It is possible to +transmit the water levels of more than 4 gauges using multiple +messages. + +//: Type 8(200/24) +[frame="topbot",options="header"] +|=============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 6 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |Designated Area Code|dac |u|Constant: 200 +|50-55 | 6 |Functional ID |fid |u|Constant: 24 +|56-67 | 12 |UN Country Code |country |t|2 six-bit characters +|68 | | |gauges |a4|Gauge measurement array +|0-10 | 11 |Gauge ID |id |u|0=unknown (default) +|11-24 | 14 |Water Level |level |i|cm, 0=unknown (default) +|=============================================================================== + +Water levels are relative to the local standard, e.g. GIW in Germany +and RNW on the Danube. + +==== Signal Strength (Inland AIS) ==== + +A message 8 subtype. DAC = 200 FID = 40. Fixed length, 168 bits. + +This message should be sent by base stations only, to inform about the +status of different light signals to all vessels in a certain +area. The information should be displayed on an external Inland ECDIS +display as dynamic symbols. The message should be sent with binary +message 8 at regular intervals. + +//: Type 8(200/40) +[frame="topbot",options="header"] +|=============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 8 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-49 | 10 |Designated Area Code|dac |u|Constant: 200 +|50-55 | 6 |Functional ID |fid |u|Constant: 40 +|56-83 | 28 |Signal Longitude |lon |I4|Minutes/10000 (as in CNB) +|84-110 | 27 |Signal Latitude |lat |I4|Minutes/10000 (as in CNB) +|111-114 | 4 |Signal form |form |u|Consult <> Annex C +|115-123 | 9 |Signal orientation |facing |u|0-39 deg, 511= N/A (default) +|124-126 | 3 |Direction of impact |direction |e|See "Signal Impact" below +|127-156 | 30 |Light Status |status |e|See "Signal Status" below +|157-167 | 11 |Spare | |x|Not used +|=============================================================================== + +OPEN-QUESTION: <> is not explicit about the interpretation of +the longitude and latitude fields; these semantics are assumed here +from 28 and 27-bit fields in other messages. + +The Signal Form field describes the physical arrangement of the +signal lights. Values 0 and 15 indicate the shape is unknown or +unspecified. + +//: direction vocabulary +.Direction of Signal Impact +[frame="topbot",options="header"] +|=============================================================================== +| 0 | Unknown (default) +| 1 | Upstream +| 2 | Downstream +| 3 | To left bank +| 4 | To right bank +|=============================================================================== + +The Signal Status field is interpreted as 9 decimal digits describing +the lights as numbered in their Signal Form diagram - typically left +to right and then top to bottom - with each digit interpreted in the +following way: + +//: status vocabulary +.Signal Status +[frame="topbot",options="header"] +|=============================================================================== +| 0 | Unknown (default) +| 1 | No light +| 2 | White +| 3 | Yellow +| 4 | Green +| 5 | Red +| 6 | White flashing +| 7 | Yellow flashing. +|=============================================================================== + +=== Type 9: Standard SAR Aircraft Position Report === + +Tracking information for search-and-rescue aircraft. Total number of +bits is 168. + +//: Type 9 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Encoding +|0-5 | 6 |Message Type |type |u|Constant: 9 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 |30 |MMSI |mmsi |u|9 decimal digits +|38-49 |12 |Altitude |alt |u|See below +|50-59 |10 |SOG |speed |u|See below +|60-60 | 1 |Position Accuracy |accuracy |u|See below +|61-88 |28 |Longitude |lon |I4|Minutes/10000 (as in CNB) +|89-115 |27 |Latitude |lat |I4|Minutes/10000 (as in CNB) +|116-127 |12 |Course Over Ground |course |U1|True bearing, 0.1 degree units +|128-133 | 6 |Time Stamp |second |u|UTC second. +|134-141 | 8 |Regional reserved |regional |x|Reserved +|142-142 | 1 |DTE |dte |b|0=Data terminal ready, + 1=Data terminal not ready (default) +|143-145 | 3 |Spare | |x|Not used +|146-146 | 1 |Assigned |assigned |b|Assigned-mode flag +|147-147 | 1 |RAIM flag |raim |b|As for common navigation block +|148-167 |20 |Radio status |radio |u|See <> for details. +|============================================================================== + +Altitude is in meters. The special value 4095 indicates altitude is +not available; 4094 indicates 4094 meters or higher. + +Speed over ground is in knots, not deciknots as in the common +navigation block; planes go faster. The special value 1023 indicates +speed not available, 1022 indicates 1022 knots or higher. + +Position Accuracy, Longitude, Latitude, and Course over Ground +are encoded identically as in the common navigation block and +are even at the same bit offsets. Time stamp has the same special +values as in the common navigation block, but is at a different offset. + +=== Type 10: UTC/Date Inquiry === + +Request for UTC/Date information from an AIS base station. Total +number of bits is 72. + +//: Type 10 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Encoding +|0-5 | 6 |Message Type |type |u|Constant: 10 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 |30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-69 |30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70-71 | 2 |Spare | |x|Not used +|============================================================================== + +=== Type 11: UTC/Date Response === + +Identical to message 4, with the semantics of a response to inquiry. + +=== Type 12: Addressed Safety-Related Message === + +This is a point-to-point text message. The payload is interpreted as +six-bit text. This message is variable in length up to a maximum of +1008 bits (up to 5 AIVDM sentence payloads). + +//: Type 12 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 12 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 +|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits +|70 | 1 |Retransmit flag |retransmit |b|0 = no retransmit (default), + 1 = retransmitted +|71 | 1 |Spare | |x|Not used +|72 |936 |Text |text |t|1-156 chars of six-bit text. + May be shorter than 936 bits. +|============================================================================== + +Pragmatic note: On <<>> the actual content of these messages is +highly variable, ranging from fairly plain English ("PLEASE REPORT TO +JOBOURG TRAFFIC CHANNEL 13") through snippets of tabular data ("PAX +589 FG 36 IX 74 MOTO 10 CREW 108+1" through what look like opaque +commercial codes ("EP285 IX46 FG3 DK8 PL56") to empty strings and +content that looks like line noise ("]XFD5D/\7`>PA!Q DX0??K?8?>D"). + +Such apparently garbled content does *not* mean there is an error in +your decoder. It may indicate faulty encoders, operator error, or even +the use of private encodings for non-ASCII character sets. + +=== Type 13: Safety-Related Acknowledgement === + +Message type 13 is a receipt acknowledgement to senders of +previous messages of type 12. The message layout is identical to +a type 7 Binary Acknowledge. + +=== Type 14: Safety-Related Broadcast Message === + +This is a broadcast text message. The payload is interpreted as +six-bit text. This message is variable in length up to a maximum of +1008 bits (up to 5 AIVDM sentence payloads). + +//: Type 14 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 14 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40 |968 |Text |text |t|1-161 chars of six-bit text. + May be shorter than 968 bits. +|============================================================================== + +Note: 161 * 6 = 966. <> specifies 968 because over-the-air +messages are required to be padded to an 8-bit byte boundary by +<<>>. + +Also see the pragmatic note on message content attached to type 12; it +applies to type 14 messages as well. + +=== Type 15: Interrogation === + +Message type 15 is used by a base station to query one or two other AIS +transceivers for status messages of specified types. "Source MMSI" is +the interrogating station. 88-160 bits depending on the number of queries. + +This message is probably not interesting unless you are doing traffic +analysis of information flow in an AIS station network. The "slot offset" +members are a request for the response to interrogation to occupy +a particular time division in the TDMA packet layer. + +//: Type 15 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 15 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-69 | 30 |Interrogated MMSI |mmsi1 |u|9 decimal digits +|70-75 | 6 |First message type |type1_1 |u|Unsigned integer +|76-87 | 12 |First slot offset |offset1_1 |u|Unsigned integer +|88-89 | 2 |Spare | |x|Not used +|90-95 | 6 |Second message type |type1_2 |u|Unsigned integer +|96-107 | 12 |Second slot offset |offset1_2 |u|Unsigned integer +|108-109 | 2 |Spare | |x|Not used +|110-139 | 30 |Interrogated MMSI |mmsi2 |u|9 decimal digits +|140-145 | 6 |First message type |type2_1 |u|Unsigned integer +|146-157 | 12 |First slot offset |offset2_1 |u|Unsigned integer +|158-159 | 2 |Spare | |x|Not used +|============================================================================== + +There are four use cases for this message. A decoder must dispatch on +the length of the data packet to determine which it is seeing: + +1. One station is interrogated for one message type. Length is 88 bits. + +2. One station is interrogated for two message types, Length is 110 +bits. There is a design error in the standard here; according to the +<<>> requirement for padding to 8 bits, this should have been +112 with a 4-bit trailing spare field, and decoders should be prepared +to handle that length as well. See the discussion of byte alignment +elsewhere in this document for context. + +3. Two stations are interrogated for one message type each. Length is +160 bits. The second message type and second slot offset associated +with the first queried MMSI should be zeroed. + +4. One station is interrogated for two message types, and a second for +one message type. Length is 160 bits. + +=== Type 16: Assignment Mode Command === + +Message type 16 is used by a base station with control authority to +configure the scheduling of AIS informational messages from +subordinate stations, either as a frequency per 10-minute interval or +by specifying the TDMA slot(s) offset on which those messages should +be transmitted. It is probably not of interest unless you are +studying the internal operation of an AIS base station network. +Length may be 96 or 144 bits. + +//: Type 16 +[frame="topbot",options="header"] +|============================================================================ +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 16 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-69 | 30 |Destination A MMSI |mmsi1 |u|9 decimal digits +|70-81 | 12 |Offset A |offset1 |u|See <> +|82-91 | 10 |Increment A |increment1 |u|See <> +|92-121 | 30 |Destination B MMSI |mmsi2 |u|9 decimal digits +|122-133 | 12 |Offset B |offset2 |u|See <> +|134-143 | 10 |Increment B |increment2 |u|See <> +|============================================================================= + +If the message is 96 bits long, it should be interpreted as an +assignment for a single station (92 bits) followed by 4 bits of +padding reserved for future use. If the message is 144 bits long it +should be interpreted as a channel assignment for two stations; no +padding follows. + +When increment is zero, the offset field is interpreted as the +frequency with which the subordinate station should report per +10-minute interval. When increment is nonzero, reporting interval +is specified at the level of TDMA slot numbers; see <> for the +detailed specification. + +Note: While the 96-bit form of Type 16 is not uncommon, the 144-bit +form is extremely rare. As of March 2010 it has not been observed even +in long-duration samples from AISHub. + +=== Type 17: DGNSS Broadcast Binary Message === + +Message type 17 is used to broadcast differential corrections for GPS. +The data in the payload is intended to be passed directly to GPS +receivers capable of accepting such corrections. 80 to 816 bits +depending on payload size. + +//: Type 17 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 17 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-57 | 18 |Longitude |lon |I1|Signed: minutes/10 +|58-74 | 17 |Latitude |lat |I1|Signed: minutes/10 +|75-79 | 5 |Spare | |x|Not used - reserved +|80-815 |736 |Payload |data |d|DGNSS correction data +|============================================================================== + +Note that latitude and longitude are in units of a tenth of a minute; +sign interpretation and out-of-band values are as in the Common +Navigation Clock. (Note, however, that the hex representation of +the out-of-band values differs; it is 181 \* 60 \* 10 = 0x1a838 for +longitude, 91 \* 60 \* 10 = 0xd548 for latitude.) + +The <> description of the payload portion subfields has been +omitted, as it appears to be tied to the now obsolete RTCM2 protocol. + +=== Type 18: Standard Class B CS Position Report === + +A less detailed report than types 1-3 for vessels using Class B +transmitters. Omits navigational status and rate of turn. Fields are +encoded as in the common navigation block. 168 bits total. + +In <> (and <>) bits 141-145 were designated "Spare"; the +bit-flag semantics given here are from ITU-1371-3 and were +communicated by Kurt Schwehr. Kurt warns that "the spec does not do a +good job of explaining these fields... I don't think that I totally +understand these fields." + +//: Type 18 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 18 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 |30 |MMSI |mmsi |u|9 decimal digits +|38-45 | 8 |Regional Reserved |reserved |x|Not used +|46-55 |10 |Speed Over Ground |speed |U1|As in common navigation block +|56-56 | 1 |Position Accuracy |accuracy |b|See below +|57-84 |28 |Longitude |lon |I4|Minutes/10000 (as in CNB) +|85-111 |27 |Latitude |lat |I4|Minutes/10000 (as in CNB) +|112-123 |12 |Course Over Ground |course |U1|0.1 degrees from true north +|124-132 | 9 |True Heading |heading |u|0 to 359 degrees, 511 = N/A +|133-138 | 6 |Time Stamp |second |u|Second of UTC timestamp. +|139-140 | 2 |Regional reserved |regional |u|Uninterpreted +|141-141 | 1 |CS Unit |cs |b|0=Class B SOTDMA unit + 1=Class B CS (Carrier Sense) unit +|142-142 | 1 |Display flag |display |b|0=No visual display, + 1=Has display, + (Probably not reliable). +|143-143 | 1 |DSC Flag |dsc |b|If 1, unit is attached to a VHF + voice radio with DSC capability. +|144-144 | 1 |Band flag |band |b|Base stations can command units + to switch frequency. If this flag + is 1, the unit can use any part + of the marine channel. +|145-145 | 1 |Message 22 flag |msg22 |b|If 1, unit can accept a channel + assignment via Message Type 22. +|146-146 | 1 |Assigned |assigned |b|Assigned-mode flag: + 0 = autonomous mode (default), + 1 = assigned mode. +|147-147 | 1 |RAIM flag |raim |b|As for common navigation block +|148-167 |20 |Radio status |radio |u|See <> for details. +|============================================================================== + +The radio status is 20 bits rather than 19 because an extra first bit +selects whether it should be interpreted as a SOTDMA or ITDMA state. + +=== Type 19: Extended Class B CS Position Report === + +A slightly more detailed report than type 18 for vessels using Class B +transmitters. Omits navigational status and rate of turn. Fields are +encoded as in the common navigation block and the Type 5 message. +Note that until just before the reserved field at bit 139 this is +identical to message 18. 312 bits total. + +In practice, the information in the ship name and dimension fields is +not reliable, as it has to be hand-entered by humans rather than +gathered automatically from sensors. + +//: Type 19 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 19 +|6-7 | 2 |Repeat Indicator |repeat |u|As in CNN +|8-37 | 30 |MMSI |mmsi |u|9 digits +|38-45 | 8 |Regional Reserved |reserved |u| +|46-55 | 10 |Speed Over Ground |speed |U1|As in CNB. +|56-56 | 1 |Position Accuracy |accuracy |b|As in CNB. +|57-84 | 28 |Longitude |lon |I4|Minutes/10000 (as in CNB) +|85-111 | 27 |Latitude |lat |I4|Minutes/10000 (as in CNB) +|112-123 | 12 |Course Over Ground |course |U1|Relative to true north, + units of 0.1 degrees +|124-132 | 9 |True Heading |heading |u|0 to 359 degrees, + 511 = N/A +|133-138 | 6 |Time Stamp |second |u|Second of UTC timestamp. +|139-142 | 4 |Regional reserved |regional |u|Uninterpreted +|143-262 |120 |Name |shipname |s|20 6-bit characters +|263-270 | 8 |Type of ship and cargo |shiptype |u|As in Message 5 +|271-279 | 9 |Dimension to Bow |to_bow |u|Meters +|280-288 | 9 |Dimension to Stern |to_stern |u|Meters +|289-294 | 6 |Dimension to Port |to_port |u|Meters +|295-300 | 6 |Dimension to Starboard |to_starboard |u|Meters +|301-304 | 4 |Position Fix Type |epfd |e|See "EPFD Fix Types" +|305-305 | 1 |RAIM flag |raim |b|As in CNB. +|306-306 | 1 |DTE |dte |b|0=Data terminal ready, + 1=Not ready (default). +|307-307 | 1 |Assigned mode flag |assigned |u|See <> for details +|308-311 | 4 |Spare | |x|Unused, should be zero +|============================================================================== + +=== Type 20 Data Link Management Message === + +This message is used to pre-allocate TDMA slots within an AIS base +station network. It contains no navigational information, and is +unlikely to be of interest unless you are implementing or studying +an AIS base station network. Length varies from 72-160 depending on +the number of slot reservations (1 to 4) in the message. + +//: Type 20 +[frame="topbot",options="header"] +|=============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 20 +|6-7 | 2 |Repeat Indicator |repeat |u|As in CNB +|8-37 |30 |MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-51 |12 |Offset number 1 |offset1 |u|Reserved offset number +|52-55 | 4 |Reserved slots |number1 |u|Consecutive slots +|56-58 | 3 |Time-out |timeout1 |u|Allocation timeout in minutes +|59-69 |11 |Increment |increment1 |u|Repeat increment +|70-81 |12 |Offset number 2 |offset2 |u|Reserved offset number +|82-85 | 4 |Reserved slots |number2 |u|Consecutive slots +|86-88 | 3 |Time-out |timeout2 |u|Allocation timeout in minutes +|89-99 |11 |Increment |increment2 |u|Repeat increment +|100-111 |12 |Offset number 3 |offset3 |u|Reserved offset number +|112-115 | 4 |Reserved slots |number3 |u|Consecutive slots +|116-118 | 3 |Time-out |timeout3 |u|Allocation timeout in minutes +|119-129 |11 |Increment |increment3 |u|Repeat increment +|130-141 |12 |Offset number 4 |offset4 |u|Reserved offset number +|142-145 | 4 |Reserved slots |number4 |u|Consecutive slots +|146-148 | 3 |Time-out |timeout4 |u|Allocation timeout in minutes +|149-159 |11 |Increment |increment4 |u|Repeat increment +|=============================================================================== + +See <> for details on the meaning of these fields. + +=== Type 21: Aid-to-Navigation Report === + +Identification and location message to be emitted by aids to +navigation such as buoys and lighthouses. + +This message is unusual in that it varies in length depending on the +presence and size of the Name Extension field. May vary between 272 +and 360 bits. + +//: Type 21 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 21 +|6-7 | 2 |Repeat Indicator |repeat |u|As in CNB +|8-37 |30 |MMSI |mmsi |u|9 digits +|38-42 | 5 |Aid type |aid_type |e|See "Navaid Types" +|43-162 1|120 |Name |name |t|Name in sixbit chars +|163-163 | 1 |Position Accuracy |accuracy |b|As in CNB +|164-191 |28 |Longitude |lon |I4|Minutes/10000 (as in CNB) +|192-218 |27 |Latitude |lat |I4|Minutes/10000 (as in CNB) +|219-227 | 9 |Dimension to Bow |to_bow |u|Meters +|228-236 | 9 |Dimension to Stern |to_stern |u|Meters +|237-242 | 6 |Dimension to Port |to_port |u|Meters +|243-248 | 6 |Dimension to Starboard |to_starboard|u|Meters +|249-252 | 4 |Type of EPFD |epfd |e|As in Message Type 4 +|253-258 | 6 |UTC second |second |u|As in Message Types 1-3 +|259-259 | 1 |Off-Position Indicator |off_position|b|See Below +|260-267 | 8 |Regional reserved |regional |u|Uninterpreted +|268-268 | 1 |RAIM flag |raim |b|As in CNB +|269-269 | 1 |Virtual-aid flag |virtual_aid |b|See Below +|270-270 | 1 |Assigned-mode flag |assigned |b|See <> for details +|271-271 | 1 |Spare | |x|Not used +|272-360 |88 |Name Extension | |t|See Below +|============================================================================== + +According to <>, the aid type field has values 1-15 for fixed +and 16-31 for floating aids to navigation. The detailed list is as follows: + +.Navaid Types +[frame="topbot",options="header"] +|==================================================================== +|Code |Definition +|0 |Default, Type of Aid to Navigation not specified +|1 |Reference point +|2 |RACON (radar transponder marking a navigation hazard) +|3 |Fixed structure off shore, such as oil platforms, wind farms, +| rigs. (Note: This code should identify an obstruction that is +| fitted with an Aid-to-Navigation AIS station.) +|4 |Spare, Reserved for future use. +|5 |Light, without sectors +|6 |Light, with sectors +|7 |Leading Light Front +|8 |Leading Light Rear +|9 |Beacon, Cardinal N +|10 |Beacon, Cardinal E +|11 |Beacon, Cardinal S +|12 |Beacon, Cardinal W +|13 |Beacon, Port hand +|14 |Beacon, Starboard hand +|15 |Beacon, Preferred Channel port hand +|16 |Beacon, Preferred Channel starboard hand +|17 |Beacon, Isolated danger +|18 |Beacon, Safe water +|19 |Beacon, Special mark +|20 |Cardinal Mark N +|21 |Cardinal Mark E +|22 |Cardinal Mark S +|23 |Cardinal Mark W +|24 |Port hand Mark +|25 |Starboard hand Mark +|26 |Preferred Channel Port hand +|27 |Preferred Channel Starboard hand +|28 |Isolated danger +|29 |Safe Water +|30 |Special Mark +|31 |Light Vessel / LANBY / Rigs +|==================================================================== + +The name field is up to 20 characters of 6-bit ASCII. If this field +is full (has no trailing @ characters) the decoder should interpret +the Name Extension field later in the message (no more than 14 6-bit +characters) and concatenate it to this one to obtain the full name. + +<> describes bits 219-248 As "Dimension/Reference for Position", +implying that it is vessel dimensions as in message type 5. + +The Off-Position Indicator is for floating Aids-to-Navigation only: 0 +means on position; 1 means off position. Only valid if UTC second is equal to +or below 59. + +The Virtual Aid flag is interpreted as follows: 0 = default = real Aid +to Navigation at indicated position; 1 = virtual Aid to +Navigation simulated by nearby AIS station. + +If present, the Name Extension consists of packed six-bit ASCII +characters followed by 0-6 bits of padding to an 8-bit boundary. The +<> description says "This parameter should be omitted when no +more than 20 characters for the name of the A-to-N are needed in +total. Only the required number of characters should be transmitted, +i.e. no @-character should be used." A decoder can deduce the bit length +of the name extension field by subtracting 272 from the total message +bit length. + +=== Type 22: Channel Management === + +This message is broadcast by a competent authority (an AIS network +control base station) to set VHF parameters for an AIS coverage +region. Length is 168 bits. + +This message contains no navigational information, and is unlikely to be of +interest unless you are implementing or studying an AIS base station +network. + +//: Type 22 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Constant: 22 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 |30 |MMSI |mmsi |u|9 decimal digits +|38-39 | 2 |Spare | |x|Not used +|40-51 |12 |Channel A |channel_a |u|Channel number +|52-63 |12 |Channel B |channel_b |u|Channel number +|64-67 | 4 |Tx/Rx mode |txrx |u|Transmit/receive mode +|68-68 | 1 |Power |power |b|Low=0, high=1 +|69-86 |18 |NE Longitude |ne_lon |I1|NE longitude to 0.1 minutes +|87-103 |17 |NE Latitude |ne_lat |I1|NE latitude to 0.1 minutes +|104-121 |18 |SW Longitude |sw_lon |I1|SW longitude to 0.1 minutes +|122-138 |17 |SW Latitude |sw_lat |I1|SW latitude to 0.1 minutes +|69-98 |30 |MMSI1 |dest1 |u|MMSI of destination 1 +|104-133 |30 |MMSI2 |dest2 |u|MMSI of destination 2 +|139-139 | 1 |Addressed |addressed |b|0=Broadcast, 1=Addressed +|140-140 | 1 |Channel A Band |band_a |b|0=Default, 1=12.5kHz +|141-141 | 1 |Channel B Band |band_b |b|0=Default, 1=12.5kHz +|142-144 | 3 |Zone size |zonesize |u|Size of transitional zone +|145-167 |23 |Spare | |x|Reserved for future use +|============================================================================== + +The values of the channel_a and channel_b fields are ITU frequency +designators for channels A and B. Normally these will be 2087 and +2088, the AIS 1 and AIS 2 frequencies of 87B (161.975 MHz) and 88B +(162.025 MHz) respectively. Regional authorities may set different +frequencies. + +The txrx field encodes the same information as the 2-bit field txrx +field in message type 23; only the two low bits are used. + +The power bit instructs designated receivers which power level to use. + +If the message is broadcast (addressed field is 0), the ne_lon, +ne_lat, sw_lon, and sw_lat fields are the corners of a rectangular +jurisdiction area over which control parameters are to be set. If it +is addressed (addressed field is 1), the same span of data is +interpreted as two 30-bit MMSIs beginning at at bit offsets 69 and 104 +respectively. + +Yes, the addressed bit is *after* the fields it controls the +interpretation of. + +Note that the 'not available' values for longitude and latitudes +match the short ones used in message 17, not the long ones used in the +common navigation block and elsewhere. + +The band fields control channel bandwidth for channels A and B, and +the zonesize field describes the size of the transition zone around the +control jurisdiction. The semantics of these fields are complicated, +controlling transmitter behavior as it moves between jurisdictions; +see <> for full details. + +=== Type 23: Group Assignment Command === + +This message is intended to be broadcast by a competent authority (an +AIS network-control base station) to set operational parameters for +all mobile stations in an AIS coverage region. Length is 160 bits. + +This message contains no navigational information, and is unlikely to +be of interest unless you are implementing or studying an AIS base +station network. + +//: Type 23 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |T|Units +|0-5 | 6 |Message Type |type |u|Unsigned Integer: 23 +|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block +|8-37 |30 |MMSI |mmsi |u|Unsigned Integer: 9 digits +|38-39 | 2 |Spare | |x|Not used +|40-57 |18 |NE Longitude |ne_lon |u|Same as broadcast type 22 +|58-74 |17 |NE Latitude |ne_lat |u|Same as broadcast type 22 +|75-92 |18 |SW Longitude |sw_lon |u|Same as broadcast type 22 +|93-109 |17 |SW Latitude |sw_lat |u|Same as broadcast type 22 +|110-113 | 4 |Station Type |station_type |e|See "Station Types" +|114-121 | 8 |Ship Type |ship_type |e|See "Ship Types" +|122-143 |22 |Spare | |x|Not used +|144-145 | 2 |Tx/Rx Mode |txrx |u|See "Tranmit/Recieve Modes" +|146-149 | 4 |Report Interval |interval |e|See "Station Intervals" +|150-153 | 4 |Quiet Time |quiet |u|0 = none, 1-15 quiet time in minutes +|154-159 | 6 |Spare | |x|Not used +|============================================================================== + +The target set of mobile stations is specified by the station-type and +ship-type fields. An addressed (non-broadcast) message 22 overrides a +message 23, but a message 23 overrides a broadcast message 22. + +Note that the 'not available' values for longitude and latitudes +match the short ones used in messages 17 and 22, not the long ones +used in the common navigation block and elsewhere. + +The txrx field tells the affected stations which channel or +channels they may transmit on. The options refer to the same A and B +VHF channels as in Message Type 22. The field is interpreted as follows: + +.Transmit Modes +[width="25%",frame="topbot"] +|=================================== +|0 = |TxA/TxB, RxA/RxB (default) +|1 = |TxA, RxA/RxB +|2 = |TxB, RxA/RxB +|3 = |Reserved for Future Use +|=================================== + +.Station Types +[width="50%",frame="topbot"] +|====================================================== +|0 |All types of mobiles (default) +|1 |Reserved for future use +|2 |All types of Class B mobile stations +|3 |SAR airborne mobile station +|4 |Aid to Navigation station +|5 |Class B shipborne mobile station (IEC62287 only) +|6-9 |Regional use and inland waterways +|10-15 |Reserved for future use +|====================================================== + +<> specifies 6 (only) as the station type value for inland +waterways, reserving 7-9 for (other) regional uses. + +Reporting Interval is a 4 bit unsigned integer, how often to report +while within the area specified by this message. When the dual-channel +operation is suspended by Tx/Rx mode command 1 or 2, the reporting +interval is twice the interval given in the table. + +.Station Intervals +[width="50%",frame="topbot"] +|====================================================== +|0 |As given by the autonomous mode +|1 |10 Minutes +|2 |6 Minutes +|3 |3 Minutes +|4 |1 Minute +|5 |30 Seconds +|6 |15 Seconds +|7 |10 Seconds +|8 |5 Seconds +|9 |Next Shorter Reporting Interval +|10 |Next Longer Reporting Interval +|11-15 |Reserved for future use +|====================================================== + +Quiet Time is a 4 bit unsigned integer specifying how many minutes +affected stations are to remain silent. If a class B station receives +a quiet time command, it will continue to schedule nominal +transmission time periods, but is not to transmit message 18 or 24 +during the quiet period. + +=== Type 24: Static Data Report === + +Equivalent of a Type 5 message for ships using Class B equipment. Also +used to associate an MMSI with a name on either class A or class B equipment. + +A "Type 24" may be in part A or part B format; According to the +standard, parts A and B are expected to be broadcast in adjacent +pairs; in the real world they may (due to quirks in various +aggregation methods) be separated by other sentences or even +interleaved with different Type 24 pairs; decoders must cope with +this. The interpretation of some fields in Type B format changes +depending on the range of the Type B MMSI field. 160 bits for part A, +168 bits for part B. + +According to the standard, both the A and B parts are supposed to +be 168 bits. However, in the wild, A parts are often transmitted +with only 160 bits, omitting the 'spare' 7 bits at the end. +Implementers should be permissive about this. + +<> does not describe this message type; format information +is thanks to Kurt Schwehr. + +//: Type 24 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description | Member |T|Units +|0-5 | 6 | Message Type | type |u|Constant: 24 +|6-7 | 2 | Repeat Indicator | repeat |u|As in CNB +|8-37 | 30 | MMSI | mmsi |u|9 digits +|38-39 | 2 | Part Number | partno |u|0-1 +|40-159 |120 | Vessel Name | shipname |t|(Part A) 20 sixbit chars +|160-167 | 8 | Spare | |x|(Part A) Not used +|40-47 | 8 | Ship Type | shiptype |e|(Part B) See "Ship Types" +|48-65 | 18 | Vendor ID | vendorid |t|(Part B) 3 six-bit chars +|66-69 | 4 | Unit Model Code | model |u|(Part B) +|70-89 | 20 | Serial Number | serial |u|(Part B) +|90-131 | 42 | Call Sign | callsign |t|(Part B) As in Message Type 5 +|132-140 | 9 | Dimension to Bow | to_bow |u|(Part B) Meters +|141-149 | 9 | Dimension to Stern | to_stern |u|(Part B) Meters +|150-155 | 6 | Dimension to Port | to_port |u|(Part B) Meters +|156-161 | 6 | Dimension to Starboard| to_starboard |u|(Part B) Meters +|132-161 | 30 | Mothership MMSI | mothership_mmsi|u|(Part B) See below +|162-167 | 6 | Spare | |x|(Part B) Not used +|=============================================================================== + +If the Part Number field is 0, the rest of the message is interpreted +as a Part A; if it is 1, the rest of the message is interpreted +as a Part B; values 2 and 3 are not allowed. + +Bits 48-89 are as described in ITU-R 1371-4. In earlier versions to +1371-3 this was one sixbit-encoded 42-bit (7-character) string field, +the name of the AIS equipment vendor. The last 4 characters of +the string are reinterpreted as a model/serial numeric pair. It is not +clear that field practice has caught up with this incompatible change. +Implementations would be wise to decode that but span in both ways and +trust human eyes to detect when the final 4 characters of the string +or the model and serial fields are garbage. + +Interpretation of the 30 bits 132-162 in Part B is variable. If the +MMSI at 8-37 is that of an auxiliary craft, the entry is taken to +refer to a small attached auxiliary vessel and these 30 bits are read +as the MMSI of the mother ship. Otherwise the 30 bits describe vessel +dimensions as in Message Type 5. + +According to <>, an MMSI is associated with an auxiliary craft +when it is of the form 98XXXYYYY, where (1) the '98' in positions 1 +and 2 is required to designate an auxiliary craft, (2) the digits XXX +in the 3, 4 and 5 positions are the MID (the three-digit country code +as described in <>) and (3) YYYY is any decimal literal from +0000 to 9999. + +=== Type 25: Single Slot Binary Message === + +Maximum of 168 bits (a single slot). Fields after the Destination +MMSI are at variable offsets depending on that flag and the Destination +Indicator; they always occur in the same order but some may be omitted. + +//: Type 25 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description | Member |T|Units +|0-5 | 6 | Message Type | type |u|Constant: 25 +|6-7 | 2 | Repeat Indicator | repeat |u|As in CNB +|8-37 | 30 | MMSI | mmsi |u|9 digits +|38 | 1 | Destination indicator | addressed |b|0=broadcast, + 1=addressed. +|39 | 1 | Binary data flag | structured |b|See below +|40 |0/30 | Destination MMSI | dest_mmsi |u|Message destination +|? |0/16 | Application ID | app_id |u|Unsigned integer +|? |0-128 | Data | data |d|Binary data +|=============================================================================== + +If the 'addressed' flag is on, 30 bits of data at offset 40 are +interpreted as a destination MMSI. Otherwise that field span becomes +part of the message payload, with the first 16 bits used as an +Application ID if the 'structured' flag is on. + +If the 'structured' flag is on, a 16-bit application identifier is +extracted; this field is to be interpreted as a 10 bit DAC and 6-bit +FID as in message types 6 and 8. Otherwise that field span becomes +part of the message payload. + +The data fields are not, in contrast to message type 26, followed by a +radio status block. + +Note: Type 25 is extremely rare. As of April 2011 it has not been +observed even in long-duration samples from AISHub. + +=== Type 26: Multiple Slot Binary Message === + +Takes up 60-1064 bits (up to 5 slots). + +//: Type 26 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description | Member |T|Units +|0-5 | 6 | Message Type | type |u|Constant: 26 +|6-7 | 2 | Repeat Indicator | repeat |u|As in CNB +|8-37 | 30 | MMSI | mmsi |u|9 digits +|38 | 1 | Destination indicator| addressed |b|0=broadcast, + 1=addressed. +|39 | 1 | Binary data flag | structured |b|See below +|40 |0/30 | Destination MMSI | dest_mmsi |u|Message destination +|? |0/16 | Application ID | app_id |u|Unsigned integer +|? |0-1004| Data | data |d|Binary data +|? |20 | Radio status | radio |u|See <> for details. +|=============================================================================== + +The data field may span up to 5 256-bit slots in addition to the tail +end of the base slot. The application_ID field, if present, is to be +interpreted as a 10 bit DAC and 6-bit FID as in message types 6 and 8. +Documentation says the data length of each slot is 224 and adds the +note "Allows for 32 bits of bit-stuffing." + +The 20 radio status bits are always present after end-of-data in the +last slot and are in the format specified by <>. The radio +status is 20 bits rather than 19 because an extra first bit selects +whether it should be interpreted as a SOTDMA or ITDMA state. + +Note: Type 26 is extremely rare. As of April 2011 it has not been +observed even in long-duration samples from AISHub. + +=== Type 27: Long Range AIS Broadcast message === + +ITU-1371-4 says this message is primarily intended for long-range +detection of AIS Class A equipped vessels (typically by +satellite). This message has a similar content to Messages 1, 2 and 3, +but the total number of bits has been compressed to allow for +increased propagation delays associated with long-range detection + +Length according to ITU-1374 is 96 bits. However, in the wild these +are sometimes transmitted with 168 bits (a full slot). Robust decoders +should warn when this occurs but decode the first 96 bits. + +//: Type 27 +[frame="topbot",options="header"] +|============================================================================== +|Field |Len |Description |Member |u|Units +|0-5 | 6 |Message Type |type |u|Constant: 27 +|6-7 | 2 |Repeat Indicator |repeat |u|As in CNB +|8-37 | 30 |MMSI |mmsi |u|9 decimal digits +|38-38 | 1 |Position Accuracy |accuracy |u|See Common Navigation Block +|39-39 | 1 |RAIM flag |raim |u|See Common Navigation Block +|40-43 | 4 |Navigation Status |status |u|See Common Navigation Block +|44-61 | 18 |Longitude |lon |I4|minutes/10 + East positive, West negative + 181000 = N/A (default) +|62-78 | 17 |Latitude |lat |I4|minutes/10 + North positive, South negative + 91000 = N/A (default) +|79-84 | 6 |Speed Over Ground |speed |u|Knots (0-62); + 63 = N/A (default) +|85-93 | 9 |Course Over Ground |course |u|0 to 359 degrees, + 511 = not available. +|94-94 | 1 |GNSS Position status|gnss |u|0 = current GNSS position + 1 = not GNSS position (default) +|95-95 | 1 |Spare | |x|Not used +|============================================================================== + +== Local extensions == + +Some regional authorities extend the AIS message set. + +The St. Lawrence Seaway broadcasts hydrological and lock-scheduling +messages using special encodings of the binary data of message types 6 +and 8 (described in <>, freely available), and safety +information using types 12 and 14. These message types are listed +under the description of type 8. + +The U.S. Coast Guard has a system called PAWSS (Port and Water Safety +System) which uses extended AIS binary formats. <> says it's +intercompatible with the St. Lawrence Seaway system and describes three +PAWSS-specific messages in its Appendix A. + +Since 2007 the Port Authority of London has operated a Thames AIS +system covering the Thames River; it uses extensions of message types +6 and 8. It is describes in <>. + +Since 2006 there has been some effort to standardize inland-waterway +extensions, described in <>. It uses different message formats +and identifiers than the PAWS/St. Lawrence systems, which do not conform. +There is an AIS extension called "RIS" (River Information System) that +covers portions of the Danube River and Black Sea which does conform. + +<> standardizes some subtypes of messages 6 and 8 similar to +PAWSS messages for DAC 1, the international jurisdiction code. However, +in some cases identically named subtypes are assigned different FIDs. + +=== U.S. Coast Guard Extended AIVDM === + +You may occasionally see AIVDM packets with additional comma-separated +fields following the CRC-32 checksum. This is a semi-obsolescent +logging format used by the USCG, which has never documented it well +and plans to replace it with a new one based on NMEA 4.0. + +Here's a sample sentence and field breakdown: + +------------------------------------------------------------------------------- +!AIVDM,1,1,,B,15Cjtd0Oj;Jp7ilG7=UkKBoB0<06,0*63,s1234,d-119,T12.34567123,r003669958,1085889680 +------------------------------------------------------------------------------- + +Following the "*63" checksum are additional fields delimited by commas. +These fields provide additional metadata about the reception of each AIS +broadcast. + +The field beginning with the lower case "s" is a Relative Signal +Strength Indicator (RSSI) measurement from the receiver. This +measurement has a range of 0-65535. This is one of the parameters used +internally by the AIS receiver to determine the signal strength value as +reported in the field beginning with the lower case "d". This field only +exists when the AIS receiver provides this data. + +The field beginning with a lower case "d" is the signal strength +measurement for this broadcast in dBm. This field only exists when the +AIS receiver provides this data. + +The field beginning with the upper case "T" is the Time of Arrival +of the received broadcast in seconds from UTC 0. This field only exists +when the AIS receiver provides this data. + +Another optional field not shown is one that begins with an upper +case "S" and represents the slot number in which the reception occurred. +The field would appear after the checksum and before the station +identifier field. This field only exists when the AIS receiver provides +this data. Example: S0042 + +The field beginning with the lower case "r" is a station identifier +field. This field is always provided, regardless of the type of AIS +equipment. (Occasionally a base station identifier will be prefixed with +"b" instead.) + +The last field is a time tag based on the standard C programming +language time function. Both date and time to the nearest second can be +derived from this field. This field is always provided, regardless of +the type of AIS equipment. + +== NMEA Tag Blocks == + +Beginning with NMEA 4.10, the standard describes a way to intersperse +"tag blocks" with AIS sentences in order to supply additional +metadata, usually a Unix timestamp to be associated with a sentence +(or contiguous group of sentences such as an armored AIS Type 5). + +The tag block facility is complex, in some respects poorly specified, +and there has been yet much public discussion of it. This section +should be considered provisional and in need of improvement. + +The general format of a tag block is: an opening backslash, followed +by multiple comma-separated fields none of which may contain +backslashes, followed by an asterisk and NMEA checksum, followed by a +closing backslash. + +The following is an example of an AIS Type 1 sentence preceded by a +tag block: + +------------------------------------------------------------------------------------------------- +\g:1-2-73874,n:157036,s:r003669945,c:1241544035*4A\!AIVDM,1,1,,B,15N4cJ`005Jrek0H@9n`DW5608EP,0*13 +------------------------------------------------------------------------------------------------- + +Each comma-separated field is expected to be a type key, followed by a +colon, followed by content. The semantics of the type keys are as +follows (table from <>): + +Confusingly, there is a different standard introduced with NMEA 4.00, +IEC 62320-1, that uses the same tag block format but a slightly +different (overlapping) set of field keys + +.NMEA 4.00 Field Types +[frame="topbot",options="header"] +|=========================================================================== +| IEC | NMEA | Type | Description +| c | c | int>0 | UNIX time in seconds or milliseconds +| d | d | string | Destination (at most 15 chars) +| xGy | g | int-int-int | Sentence grouping +| x | n | int>0 | line count +| | r | int>0 | relative time +| s | s | string | Source / station +| i | t | string | Text string (at most 15 chars) +|=========================================================================== + +The IEC 62320-1 and NMEA 4.10 c field is an emission time for the +sentence it precedes. We're not yet sure what the time unit is. + +The NMEA 4.10 g value describes a sentence or sentence group to +associate the tag block to. It is a triple of ints separated by +dashes. The first number is the sentence number, the second is total +number of sentences to make up one group. The third number is an +identifier for that particular group. If there is no g value, the tag +block simply applies to the following sentence. + +As of May 2014 no NMEA 4.10 relative time fields have been observed in the +wild. It is unknown whether the unit is seconds or milliseconds. + +The d, i/t, and s fields are intended to be used for filtering by +station IDs included in them. + +Part of the NMEA 4.10 standard describes a configuration message facility by +which AIS message receivers can send queries to AIS senders, and under +some circumstances change the semantics if tag blocks (in particular, +by specifying time units and epoch). + +We do not yet have more definite information on the meaning of these +fields or how they are related to nearby AIVDM/AIVDO sentences. We +hope to add this in a future revision. + +== AIS Payload Byte Alignment, Padding, and Bit Stuffing == + +Warning: Here there be dragons. Read with care. Once you get through +it, you will at least not encounter anything more confusing in the +rest of this document. + +=== Byte Alignment === + +AIS is a bit-sync protocol. While some fields within AIS payloads are +8-bit-byte-aligned with preceding padding, most are not. Furthermore, +while most message variants have bit lengths that are a multiple of 8, +some do not. + +<> includes a single sentence, easy to miss, requiring +over-the-air messages to have trailing padding to a 8-bit boundary. +In most cases message lengths are a multiple of 8 with trailing spare +fields added to ensure this; thus, the requirement will not change the +transmitted bitlength of the message from what's described in the +standard. There are, however, two exceptions to this rule. + +One is an apparent error in the format design. The type 15 message +has a variant with 108 data bits and a trailing 2-bit spare field, for +110. This spare should have been 4 bits to guarantee a byte boundary +at 112 bits. Decoders need to be prepared to encounter this length +in case the transmitter has implemented the padding requirement +properly. + +The other is messages containing variable-length text packed into +6-bit nibbles: types 6, 12, and 14. They may have trailing padding +after the last nibble to get to an 8-bit boundary. Decoders should +be prepared to encounter and ignore this. + +The variable-length binary message types 8, 17, 25, and 26 are +constrained to have data payloads of a size such that the payload ends +on a byte boundary, but should not require special handling on this +account. The binary data in message types 8 and 17 is also guaranteed +to *begin* on a byte boundary, but this is not true of the addressed +variants of type 25 and 26. + +=== Interaction with AIVDM padding === + +AIVDM armoring introduces a second layer of padding, with confusing +consequences. The real payload, already padded to a bit length that +is a multiple of 8 by the AIS radio layer, gets armored as a sequence +of ASCII characters encoding 6-bit nibbles. To capture all of it, the +payload must in effect be padded to the next multiple of 6. + +Consider a type 12 message with 5 sixbit characters in it. These will +become bits 72-102 in the over-the-air message. The AIS radio layer will +pad that to 104 bits at transmission to get to an 8-bit boundary. The +receiver, reporting the data in AIVDM armoring, will pad that to 108 +bits to get to a 6-bit boundary, encode the result, and issue a pad +character of '4' to indicate that the low 4 bits of the last 6-bit +nibble should be ignored. + +Because these requirements are tricky and poorly documented in the +official standards, receivers not uncommonly get them wrong. The most +common way to get them wrong seems to be by computing the pad +character incorrectly. + +The most common error observed in the wild on AISHub is reporting a +pad 2 bits too small, making the message look like it is 2 bits longer +than it actually is. This seems for some reason to be most common +on Type 5 messages, which then decode as 426 bits rather than 424. + +Accordingly, we recommend that when validating fixed-size messages by +type and bit-length, decoders should accept messages that are up to 5 +bits over their theoretically correct length. + +For messages with a variable-length trailing payload (6, 8, 12, 14, +17, 25, 26) there is no way to detect that the pad character might +be wrong. If it is, this will manifest as truncation of the last +nibble or extra trailing zero data. + +=== Bit Stuffing === + +The following probably will not affect decoders. Nevertheless we +document it here because it is just the sort of thing that is (a) +likely to confuse implementors reading the public portions of the +standards, and (b) all too likely to become visible if there are +firmware or software errors in the transmission chain. + +There are references to "bit-stuffing" in the <> clarifications +describing certain payload fields. <> reveals the following in +3.2.2.1: "The bitstream is subject to bit stuffing. This means that if +more than 5 consecutive 1s are found in the output bit stream, a zero +is inserted. This applies to all bits except the databits of HDLC +flags." <> clarifies as follows: "On the transmitting side, +this means that if five (5) consecutive ones (1s) are found in the +output bit stream, a zero should be inserted after the five (5) +consecutive ones (1s). This applies to all bits between the HDLC flags +[...] On the receiving side, the first zero after five (5) consecutive +ones (1s) should be removed." + +It appears that this bit stuffing is meant to be performed by the AIS +radio link layer at transmission time and undone at reception time, +and should not be visible in AIVDM payloads reported by the +receiver. + +== AIS feed sites == + +Most sites that advertise "live" AIS feeds actually give you a map +display through a browser. Here are a few from which you can get raw +sentence data over a TCP/IP port for testing. Coverage on these is +not yet very comprehensive; these sites tend to have good coverage in +Europe, the U.S. and a few ports in Asia but to be spotty elsewhere. +See their siting maps for details. + +- http://aishub.net[AIS Hub]: +Share alike. You contribute a feed, you get back all feeds. + +- http://maritime.ihs.com[AIS Live]: +Subscription access to real-time data. No longer has free access even +to delayed data. + +- http://hd-sf.com:9009 +Free San Francisco Bay Area AIS feed. For non-commercial use only. + +== JSON-AIS encoding == + +Here is an application of the JSON metaformat to present AIS data in a +form more convenient for application use than AIVDM/AIVDO sentences. +This encoding is implemented by GPSD and its client libraries. It is +described here because (a) the specification is closely tied to the +field encodings, and (b) the author wishes to offer it as an +interoperability standard for other applications. + +One previous effort, <>, has been made to define a +JSON-based standard for exchange of unpacked, human-readable AIS +data. The latest version at time of writing, from December 2008,covers +only a small subset of the most common AIS messages, and many data +fields in the messages it does dump are omitted. The member names +given in the bit-field tables match the attributes used in HAM-JSON-AIS +when HAM-JSON-AIS includes that field. + +The general ground rules for JSON-AIS encoding are as follows: + +. Each sentence decodes to a JSON object. + +. When multiple kinds of JSON objects may occur in a data stream, AIS +objects have the attribute "class":"AIS". + +. Some collections of fields aggregating to a timestamp are dumped in +ISO8601 format. + +.Timestamp fields +[frame="topbot",options="header"] +|=========================================================================== +|Message| ITU/IMO fields | JSON ISO8601 | Format +| 4 | year,month,day,hour,minute,second| timestamp | %4u-%02u-%02uT%02u:%02u:%02uZ +| 5 | month,day,hour,minute | eta | %02u-%02uT%02u:%02uZ +|6(1/12)| lmonth,lday,lhour,lminute | departure | %02u-%02uT%02u:%02uZ +| | nmonth,nday,nhour,nminute | eta | %02u-%02uT%02u:%02uZ +|6(1/18)| month,day,hour,minute | arrival | %02u-%02uT%02u:%02uZ +|6(1/20)| month,day,hour,minute | arrival | %02u-%02uT%02u:%02uZ +|6(1/23)| month,day,hour,minute | timestamp | %02u-%02uT%02u:%02uZ +|6(1/28)| month,day,hour,minute | start | %02u-%02uT%02u:%02uZ +|8(1/11)| day,hour,minute | timestamp | %02uT%02u:%02uZ +|8(1/11)| day,hour,minute | timestamp | %02uT%02u:%02uZ +|8(1/13)| fmonth,fday,fhour,fminute | from | %02u-%02uT%02u:%02uZ +|8(1/13)| tmonth,tday,thour,tminute | to | %02u-%02uT%02u:%02uZ +|8(1/22)| month,day,hour,minute | timestamp | %02u-%02uT%02u:%02uZ +|8(1/27)| month,day,hour,minute | start | %02u-%02uT%02u:%02uZ +|8(200/23)| year,month,day,hour,minute | start |%4u-%02u-%02uT%02u:%02u +|8(200/23)| year,month,day,hour,minute | end |%4u-%02u-%02uT%02u:%02u +|=========================================================================== + +. There are two variants of the encoding, one scaled and one +unscaled, which differ in the treatment of float and +controlled-vocabulary fields. An AIS-JSON object may have the optional +attribute "scaled":true to signify that the rest of its fields are +scaled; if this attribute has the value 'false' or is omitted, no +scaling has been performed. Message types for which the unscaled and +scaled dumps will differ are 1-5, 9, 11, 17-19, 21-24, and 27. + +. In unscaled mode, float-valued fields are dumped in their unscaled +integer form. In scaled mode, division or other specified scaling is +applied and the value dumped as a float, *except* that certain extreme +or data-unavailable value as may be dumped as fixed strings; see the +table below. + +. Each field in the Controlled Vocabularies list in the following +table is dumped twice: once with its base name as an integer, once +with "_text" appended to the name and the vocabulary item as value. +(This behavior is new in GPSD protocol version 3.9; older versions +made integer or string display dependent on the "scaled" flag.) + +.Special fields +[frame="topbot",options="header"] +|=========================================================================== +|Message | Float Fields | Controlled Vocabularies +| 1-3 | turn, speed, lon, lat | status +| 4, 11 | lon, lat | epfd +| 5 | draught | shiptype, epfd +| 6(1/14)| lon, lat, cspeed | - +| 6(1/18)| lon, lat | - +| 6(1/20)| berth_lon, berth_lat, berth_depth | position +| 6(1/22)| lon, lat | - +| 6(1/25)| code | code* +| 6(1/28)| lon, lat | rtype +| 6(1/32)| lon, lat, cspeed | - +| 6(235/100) | - | racon, light +| 8(1/11)| lon, lat, airtemp, dewpoint, | preciptype, ice +| | visibility, waterlevel, cspeed, | +| | cspeed2, cspeed3, waveheight, | +| | swellheight, watertemp salinity | +| 8(1/17)| lon, lat | idtype* +| 8(1/18)| lon, lat | - +| 8(1/19)| - | signal, nextsignal +| 8(1/21)| lon, lat, visibility, airtemp, | - +| | watertemp, waveheight, | +| | swellheight, speed, pressure, pdelta,| +| | rwindspeed, mgustspeed, airtemp, | +| | surftemp, cloudbase, | +| | swheight1, swheight2 | +| 8(1/22)| lon, lat | - +| 8(1/25)| - | iceclass* +| 8(1/27)| lon, lat | rtype +| 8(1/31)| lon, lat, airtemp, dewpoint, | preciptype +| | visibility, waterlevel, cspeed, | +| | cspeed2, cdepth2, cspeed3, | +| | cdepth3, waveheight, | +| | swellheight, watertemp, salinity | +| 9 | lon, lat, course | - +| 17 | lon, lat | - +| 18 | lon, lat, course | - +| 19 | lon, lat, course | shiptype, epfd +| 21 | lon, lat | aid_type, epfd +| 22-23 | ne_lon,ne_lat, sw_lon, sw_lat | shiptype,stationtype +| 24 | - | shiptype +| 27 | lon, lat | - +|=========================================================================== + +This table does not include fields that are scaled by multipliers to integers. +These are reported in the multiplied form in both scaled and unscaled modes. + +Asterisked fields are not yet decoded by GPSD, but probably will be in +a future release. + +As the Beaufort scale is usually quoted numerically, conforming implementations +should do so rather than expanding to its controlled vocabulary. + +.String special values in scaled mode +[frame="topbot",options="header"] +|=========================================================================== +|Message | Fieldname | Special values +| 1-3 | turn | +"nan" = not available, "fastright" = fast right turn (above 5deg/30sec degrees), +"fastleft" = fast left turn (above 5deg/30sec degrees). +| 1-3 | speed | "nan" = not available, "fast" = speed >= 102.2 knots +| 9 | alt | "nan" = not available, "high" = alt >= 4094 meters +| 9 | speed | "nan" = not available, "fast" = speed >= 1023.0 knots +|=========================================================================== + +. Trailing arrays are dumped as JSON subobject arrays. The name of the +array item is the name given in the 'a' table entry. Explicit array count +fields (presently "waycount" in Route Info messages") are not dumped. + +. In the VTS-Generated/Synthetic Targets message, the id field is +dumped as the value of an attribute the name of which is specified by +the idtype field. + +== Open Questions == + +The AIS standards are not marvels of clear and unambiguous drafting. +We list here some open questions which could usefully be addressed +by governing authorities. + +Some of these duplicate material in paragraphs tagged with OPEN-QUESTION. +They are collected here for convenience. + +The message type summary table in <> indicates the existence +of a broadcast (unaddressed) variant of Inland Number of Persons On +Board. But no field breakdown is given for this variant. If it +supposed to be identical to the Type 6 layout, what is to be done +with the Destination MMSI field? + +Are <> time-of-day fields UTC or local? + +In <> RTA at lock/bridge/terminal message, no default is +specified for the Status field. + +In Inland Ship Static and Voyage Related Data, which of two possible +ERI numeric codesets are used for the Type field - the 4-digit codes +in the 8000-8073 range, or the AIS codes in the 1-99 range? Full ERI +codes have been observed in the wild. + +In the <> description of Message 5 extensions, footnote 6 is +incomprehensible and not actually referenced in the table. + +In the <> EMMA Warning and Signal Strength messages, the +description is not explicit about the interpretation of the longitude +and latitude fields; these semantics are assumed here from 28 and +27-bit fields in other messages. + +In the <> EMMA Warning, what are the semantics of the min and +max values? To what parameters do they apply? + +Is the <> versions of Persons On Board, which is supposed to +be Type 6 and thus addressed, erroneous? There is no destination +address field in the layout. + +<> says of the "VTS Generated/Synthetic Targets" message: +"When MMSI or IMO number is used, the least significant bit should +equal bit zero of the Target Identifier." It is unclear how "bit +zero" is to be interpreted, but it is not possible to reconcile +interpreting it as the leading bit of the field with AIS big-endian +encoding. Settling this awaits live testing. + +== References == + +[bibliography] +- [[[AIS]]] http://en.wikipedia.org/wiki/Automatic_Identification_System[Automatic +Identification System] + +- [[[SOLAS]]] + http://www.navcen.uscg.gov/enav/ais/AIS_Regs_SOLAS_MTSA_FR.pdf[SOLAS + AIS Regulations] + +- [[[US-REQUIREMENTS]]] + http://www.navcen.uscg.gov/enav/AIS/AIS_carriage_reqmts.htm[AIS + Carriage Requirements] + +- [[[ITU1371]]] + http://www.itu.int/rec/R-REC-M.1371/en + ITU Recommendation on the Technical Characteristics for a Universal + Shipborne Automatic Identification System (AIS) using Time Division + Multiple Access in the Maritime Mobile Band]. All versions are + available here. + +- [[[IALA]]] http://www.ialathree.org/iala/pages/AIS/IALATech1.5.pdf[IALA + Technical Clarifications on Recommendation ITU-R M.1371-1] + +- [[[NAVCEN]]] http://www.navcen.uscg.gov/enav/ais/[NAVCEN AIS pages] + +- [[[NMEA]]] "NMEA Revealed" This document collects information from + public sources on the proprietary NMEA 0183 standard. It is widely + distributed, but due to its hosting site having folded in late 2011, + its home location is unstable. It is probably best found by typing + the title into a search engine. + +- [[[INLAND]]] http://www.unece.org/fileadmin/DAM/trans/doc/finaldocs/sc3/ECE-TRANS-SC3-176e.pdf[International Standard for tracking and tracing on Inland Waterways] + +- [[[SEAWAY]]] http://www.greatlakes-seaway.com/en/pdf/aisdata.pdf[St. Lawrence + Seaway AIS Data Messaging Formats and Specifications] + +- [[[THAMES]]] http://www.pla.co.uk/pdfs/maritime/APPENDIX_I__II_amendment_for_2012_byelaws_FINAL.pdf[Thames AIS - Technical Requirements Specification] + +- [[[IMO236]]] http://www.imo.org/includes/blastData.asp/doc_id=4503&filename=236.pdf[IMO + Circular 236: Guidance on the Application of AIS Binary Messages (May 2004)] + +- [[[IMO289]]] + http://vislab-ccom.unh.edu/~schwehr/papers/2010-IMO-SN.1-Circ.289.pdf[IMO + 289: Guidance on the Use of AIS Application-Specific Messages + (June 2010)] + +- [[IALA-A126]] + http://www.ialathree.org/chapo/publications/documentspdf/doc_235_eng.pdf[IALA + Recommendation A-126 On The Use of the Automatic Identification System (AIS) + in Marine Aids to Navigation Services + +- [[[Schwehr]]] http://schwehr.org/blog/[Kurt Schwehr's weblog] + +- [[[IEC-PAS]]] IEC-PAS 61162-100, "Maritime navigation and + radiocommunication equipment and systems" The ASCII armoring + is described on page 26 of Annex C, Table C-1. Communicated by + Kurt Schwehr; I have not looked at it. + +- [[[IEC-62287]]] "Maritime Navigation and Radiocommunication + Equipment and Systems – Class B Shipborne Equipment of the + Automatic Identification System (AIS)" Communicated by Mike Greene; + I have not looked at it. + +- [[[ITU-MID]]] http://www.itu.int/cgi-bin/htsh/glad/cga_mids.sh?lng=E[Table + of Maritime Identification Digits] + +- [[[RAIM]]] http://en.wikipedia.org/wiki/RAIM[Receiver Autonomous + Integrity Monitoring] + +- [[[C2]]] http://www.uais.org/AISspecificationCorrigendum2.pdf[AIS + Specification Corrigendum 2] + +- [[[MMSI]]] http://www.navcen.uscg.gov/marcomms/gmdss/mmsi.htm#format[MMSI + Format] + +- [[[HAM-JSON-AIS]]] http://wiki.ham.fi/JSON_AIS.en[JSON AIS transmission protocol] + +- [[[AISHUB]]] http://www.aishub.net/[AIS Hub, the AIS data sharing center] + +- [[[PILOTPLUG]]] http://www.pilotplug.com/ + +- [[[IALA-A126]]] http://www.iala-aism.org/iala/publications/documentspdf/doc_299_eng.pdf[] + +- [[[AIS-SART]]] http://www.navcen.uscg.gov/?pageName=AISMessagesA + +- [[[SART]]] http://en.wikipedia.org/wiki/AIS-SART + +- [[[PATREON]]] https://www.patreon.com/esr + +- [[NMEA-ADVANCE]] http://www.nmea.org/Assets/0183_advancements_nmea_oct_1_2010%20(2).pdf + +== Change history == + +Version 1.0 was the initial release covering messages 1-3, 4, and 5. + +Version 1.1 adds message breakdowns for 9 and 18, explanation of the +Repeat Indicator feld, and the explanation of USCG extended AIVDM. + +Version 1.2 adds information on the ITU1371 edition 3 maneuver field, +and the RAIM flag. It also adds an important clarification about +six-bit decoding. + +Version 1.3 adds information on message types 6, 7, 12, and 13, and +attempts to demystify bit-stuffing. + +Version 1.4 adds explicit decoding tables for ASCII armoring and +six-bit ASCII. + +Version 1.5 corrects the interpretation of field 7 in AIVDM +ASCII-armored sentences. + +Version 1.6 corrects some minor errors in the interpretation of Type +5 messages. + +Version 1.7 adds descriptions for Type 10, 11, 19, 21, and 24 +messages, information about ITU-1371-3 flags in message type 18, +and the new section on Improving This Document. + +Version 1.8 fixes some broken markup and adds information about JSON-AIS. + +Version 1.9 adds more information on JSON and the member names. + +Version 1.10 fixes a typo in the formula for undoing 6-bit armoring. + +Version 1.11 describes message types 15, 16, and 17. + +Version 1.12 describes messages 20 and 22, and adds navigation aid +type codes. + +Version 1.13 documents more out-of-band values and treats radio status +blocks more uniformly. + +Version 1.14 documents message 23. + +Version 1.15 corrects an incorrect member name in message 5. It didn't +match my C code, but had no effect on conformance with the standard. I +corrected it because it confused someone working on a Python decoder. + +Version 1.16 incorporated various minor fixes and corrections from +Neal Arundale. One 'standard' fieldname changed, in message type 21: +type -> aid_type. + +Version 1.17 clarifies the role of @ as a terminator in 6-bit text. + +Version 1.18 notes a possible off-by-two error in the standards' +description of type 14, and noted that type 25 and 26 have not +been observed in the wild. It also adds a more complete description +of AIS data types and some pragmatics about spare and reserved fields. + +Version 1.19 adds a description of AIS Hub. + +Version 1.20 adds a list of AIS feed sites - just two, so far. + +Version 1.21 describes JSON-AIS more completely. It adds descriptions +for AIS messages type 25 and 26, not yet observed in the wild. + +Version 1.22 describes the problem with message length checks. +Notes on EPFD value 15 and shiptype values > 99 are added. Added +another AIS feed. Corrections and more details on message 22. + +Version 1.23 corrects some typos and numbering errors in the +description of message 19 (field widths were correct, though). +Also, AISLive no longer offers free delayed access. + +Version 1.24 breaks the Type 6 and 8 application_id field into +DAC and FID and adds tables for known DAC/FID pairs and their sources. +Unspecified fields are now omitted in JSON dumps. A new section +"AIS byte alignment, bit stuffing, and padding", reveals some +particularly black magic. + +Version 1.25 adds clarifications and more message subtypes for +U.S. Coast Guard PAWSS messages. + +Version 1.26 corrects an error in describing rate-of-turn decoding in +AIS Type 1, 2, and 3 messages, + +Version 1.27 describes the sometime U.S. practice of omitting the leading +'3' region code from MMSIs. + +Version 1.28 merges updates from IMO 289, communicated by Kurt Schwehr. + +Version 1.29 added much information on WMO special message formats in +types 6 and 8. + +Version 1.30 was revised because M.1371-4 is now a free download. +Also, we describe "pilot plugs" and AIS message type 27. We get +much more explicit about defaults in IMO236 and IMO289 messages. + +Version 1.31 shortened some C names in the Meteorological/Hydrological +messages and fixed typos. + +Version 1.32 adds descriptions of IMO Area Notice and Environmental +messages. It adds explicit type information to the tables. + +Version 1.33 notes that the home location of "NMEA Revealed" became +unstable in late 2011. + +Version 1.34 fixes a typo in the MMSI 2 field offset of message 7. + +Version 1.35 notes that 24A and 24B messages don't necessarily come +in neat adjacent pairs and that decoders need to handle this. + +Version 1.36 corrects erroneous scale factors in the IMO 289 Area +Notice and Time to Enter Port descriptions. + +Version 1.36 adds breakdowns of Aid to Navigation monitoring messages +used in the UK and the Republic of Ireland. + +Version 1.37 corrects a field signedness error in the IMO236 and +IMO289 Met/Hydro messages. + +Version 1.38 corrects a minor bug in the description of the Navigation +Message ROT field. Adds information on AIS-SART. + +Version 1.39 corrects signedness errors in the description of the Air +Temperature and Water Temperature fields in the IMO289 Weather Report +From Ship message. + +Version 1.40 notes that AIS channel codes '1' and '2' may be +encountered in the wild. + +Version 1.41 has been slightly amended because type 27s have started +showing up on satellite feeds. + +Version 1.42 fixes a typo in the Type 4 message description. + +Version 1.43 describes the ITU-R 1371-4 breakdown of the Type 24 +Vendor ID field and adds information on AIS standards for inland +waterways. Also Inland AIS standard messages are now covered. + +Version 1.44 adds substantial new information on MMSIs and updates +the <>, which was stale. + +Version 1.45 adds a description of variant AIS talker IDs and NMEA +4.10 tag blocks. + +Version 1.46 corrects an error in the specification on Inland AIS Type +10s. It also adds a bit more information on AIS tag blocks. + +Version 1.47 corrects some minor field type errors in Type 18 and Type +19 speed fields. Also corrected Type 9 radio field length. + +Version 1.48 corrects two typos in the WMO289 Area Notice and Weather +Report From Ship definitions. + +Version 1.49 adds a technical detail about non-AIS encapsulated +sentences. + +Version 1.50 fixes a couple of typos in the ISO289 Berthing Data and +Tidal Window message descriptions. + +Version 1.51 fixes an incorrect bit length in the IMO289 Hydrological +Data message. + +Version 1.52 fixes many small typos. Change Gratipay to Patreon. + +// end diff --git a/www/AIVDM.txt b/www/AIVDM.txt deleted file mode 100644 index e4eb929c..00000000 --- a/www/AIVDM.txt +++ /dev/null @@ -1,5438 +0,0 @@ -= AIVDM/AIVDO protocol decoding = -:description: The AIVDM Marine AIS protocol demystified, for programmers. -:keywords: AIS, AIVDM, AIVDO, standard, protocol, Automatic Identification System -Eric S. Raymond -v1.52, Aug 2016 - -This document is mastered in asciidoc format. If you are reading it in HTML, -you can find the original at the GPSD project website - -// If you are reading the asciidoc master of this document, the -// occasional comments led with '//!' are hints for GPSD developer tools -// that use the table layouts to generate code. - -If you find this document useful - and especially if it helps you make -money - please contribute to maintaining it by supporting the author's -full-time open-source work through <>. Even a few dollars a -week can make a difference. - -== Introduction == - -This is a description of how to decode AIVDM/AIVDO sentences. It -collects and integrates information from publicly available sources -and is intended to assist developers of open-source software for -interpreting these messages. - -AIVDM/AIVDO sentences are emitted by receivers for AIS, the marine -Automatic Identification System. AIS transmitters are fitted to -vessels, navigation markers, and certain types of shore station. They -periodically squawk their position (and course, when applicable), using -TDMA (Time Division Multiple Access) technology similar to the way -cellphones do to avoid mutual interference. AIS receivers make this data -available for navigation, anti-collision systems, and other uses. - -The International Maritime Organization's (IMO) International -Convention for the Safety of Life at Sea (SOLAS) requires operating AIS -transmitters on all international cargo vessels of more than 300 tons -displacement, all cargo vessels of more than 500 tons displacement, -and all passenger vessels; see <> for details. Individual -maritime nations may have stricter and more detailed rules: for those -obtaining in U.S. waters, see <>. - -AIS receivers report ASCII data packets as a byte stream over serial -or USB lines, using the NMEA 0183 or NMEA 2000 data formats. The RS422 -variant of serial specified as a physical layer by NMEA 0183 is common -in marine navigation systems; there may be a "pilot plug" -<> which converts to USB. Alternatively, newer AIS -receivers may report directly over RS232 or USB. - -AIS packets have the introducer "!AIVDM" or "!AIVDO"; AIVDM packets -are reports from other ships and AIVDO packets are reports from your -own ship. - -A lengthy description of AIS, focusing on the goals and history of the -system, but not describing the data protocols in any detail, can be -found at <>. - -== Standards == - -Multiple standards bear on the AIVDM/AIVDO format. This document -exists because assembling them into a complete picture is technically -difficult and was long impeded by legal barriers as well. - -ITU Recommendation M.1371, "Technical Characteristics for a Universal -Shipborne Automatic Identification System Using Time Division Multiple -Access" <>, issued in 2001, first described the bit-level -format of AIS radio messages. This standard was proprietary and -expensive when issued. I did not have access to it or any of its -followup revisions while assembling versions of this document up to -1.29. - -ITU-R M.1371 was expanded and clarified by "IALA Technical -Clarifications on Recommendation ITU-R M.1371-1" <>, which -is freely available. - -There have been three minor revisions of ITU-R M.1371 since it was -originally issued. These add interpretations to packet bitfields that -were previously marked "spare" and "regional reserved". ITU-R M.1371 -revision 4 became available for free download, apparently at some -point in early 2011, well after most of this document was assembled. - -The ASCII format for AIVDM/AIVDO representations of AIS radio messages -seems to have been set by IEC-PAS 61162-100, "Maritime navigation and -radiocommunication equipment and systems" <>. It is -proprietary and I have not looked at it. Various public sources -indicate that it has been "harmonized" with some version of NMEA 0183, -which I also have not looked at because it too is proprietary and -expensive, and surrounded by rapacious attack lawyers. - -== Information Sources == - -Together, the IALA Technical Clarifications at <> and the -Coast Guard's AIS pages at <> describe AIS message payloads -type 1-24 almost completely. Certain specialized binary messages of -types 6 and 8 defined by the International Maritime Organization are -described in <> and <>. The detail information on -payload formats in this document is mostly derived from these public -sources. - -Kurt Schwehr is a research scientist at the Center for Coastal and -Ocean Mapping at the University of New Hampshire. Much of his research -involves AIS. His work blog at <> contains sample messages -and descriptions of AIS operation in the wild that shed light on -various obscure corners of the specification. He has explained the -otherwise undocumented Repeat Indicator field and USCG extended AIVDM -to me by email. He also communicated some critical information from -<>, and supplied information about new messages and fields in -ITU-1371-3. - -Descriptions of messages 25 and 26 are based on AIS transceiver vendor -documentation was originally forwarded to me by a source wishing to -remain anonymous; I later checked them against ITU1371-4. Message -type 27 was described in ITU1371-4 and added here after that became a -freely available download. - -Should you set out to write a decoder using this document, you are -likely to find that one of your challenges is finding enough AIS -packet data to make an effective regression test -- especially if you -live out of line of sight of any ship traffic and would get nothing -from running an AIS receiver. Fortunately, various AIS sites offer -live feeds over the Internet that aggregate AIS streams from all over -the world. Some charge subscriptions; others offer time-delayed access -for free and charge for a real-time feed. Still others are pool sites; -you join by contributing your feed and receive all feeds. - -AIS Hub (<>) is a free, public AIS feed pool. It provides -exchange of AIS data in raw NMEA format; all AISHub members share -their own received AIS data and receive the merged feed from all other -participating parties. It is open-source friendly, offering a Linux -port in source of its software for collecting and forwarding AIS -data. Peter Stoyanov and the other AIS Hub principals have generously -donated a live feed to the GPSD project despite the fact that I live -60 miles inland and cannot send them anything interesting. - -Some of what this document explains about the quirks of real-world -encoders comes from examples provided by Kurt Schwehr. Other such -information, especially for the less common sentences, comes from -inspection of sentences forwarded to me from AIS Hub by various -interested parties, and more recently from AIS Hub itself. - -== Improving This Document == - -To avoid copyright difficulties, I rely only on freely redistributable -public documents and paraphrased reports from people who have seen the -relevant proprietary standards. If you are such a person, please help -by reporting the following to be included in future versions of this -document: - -* Sample sentences of types 16-17, 22-23, and 25-27. - -* Sample sentences of type 6 and 8 conforming to <>, - <>, and <>. - -For verification purposes, I need the raw sentences together with -decoded dumps of their field values. Please note that sample -sentences not accompanied by field dumps are *not* useful; I can get -plenty of those. - -== Open-Source Implementations == - -The GPSD project ships an AIVDM/AIVDO sentence decoder as part of the -daemon. This document was developed to be the specification for it, -and it will decode all sentence type described herein. - -The source-code repository of the GPSD project holds a conforming -standalone Python decoder, ais.py, that is not included in shipped -releases. It may be useful for developers working in that language. - -<> includes links to a collection of Python scripts for -decoding and analyzing AIVDM sentences. Kurt Schwehr warns that this -is research code rather than a production tool. - -There is a http://gnuais.sourceforge.net/[GNU AIS] project at -SourceForge. It seems intended primarily to work directly -with AIS radios. - -http://www.maritec.co.za/aisvdmvdodecoding.php[The Maritec decoder] -looks to be pretty high-quality and can be exercised through a -public web form. This is a useful resource for anyone qualifying -an AIS decoder. - -== AIVDM/AIVDO Sentence Layer == - -AIVDM/AIVDO is a two-layer protocol. The outer layer is a variant of -NMEA 0183, the ancient standard for data interchange in marine -navigation systems; NMEA 0183 is described at <>. - -Here is a typical AIVDM data packet: - --------------------------------------------------------------------- -!AIVDM,1,1,,B,177KQJ5000G?tO`K>RA1wUbN0TKH,0*5C --------------------------------------------------------------------- - -And here is what the fields mean: - -Field 1, !AIVDM, identifies this as an AIVDM packet. - -Field 2 (1 in this example) is the count of fragments in the currently -accumulating message. The payload size of each sentence is limited by -NMEA 0183's 82-character maximum, so it is sometimes required to split -a payload over several fragment sentences. - -Field 3 (1 in this example) is the fragment number of this -sentence. It will be one-based. A sentence with a fragment count of -1 and a fragment number of 1 is complete in itself. - -Field 4 (empty in this example) is a sequential message ID for -multi-sentence messages. - -Field 5 (B in this example) is a radio channel code. AIS uses the high -side of the duplex from two VHF radio channels: AIS Channel A is -161.975Mhz (87B); AIS Channel B is 162.025Mhz (88B). In the wild, -channel codes '1' and '2' may also be encountered; the standards -do not prescribe an interpretation of these but it's obvious enough. - -Field 6 (177KQJ5000G?tO`K>RA1wUbN0TKH in this example) is the data -payload. We'll describe how to decode this in later sections. - -Field 7 (0) is the number of fill bits requires to pad the data -payload to a 6 bit boundary, ranging from 0 to 5. Equivalently, -subtracting 5 from this tells how many least significant bits of the -last 6-bit nibble in the data payload should be ignored. Note that -this pad byte has a tricky interaction with the <<>> -requirement for byte alignment in over-the-air AIS messages; see the -detailed discussion of message lengths and alignment in a later -section. - -The \*-separated suffix (\*5C) is the NMEA 0183 data-integrity checksum -for the sentence, preceded by "*". It is computed on the entire -sentence including the AIVDM tag but excluding the leading "!". - -For comparison, here is an example of a multifragment sentence with a -nonempty message ID field: - --------------------------------------------------------------------- -!AIVDM,2,1,3,B,55P5TL01VIaAL@7WKO@mBplU@>, the valid ASCII characters for -this encoding begin with "0" (64) and end with "w" (87); however, the -intermediate range "X" (88) to "\_" (95) is not used. - -.ASCII payload armoring -[width="25%",frame="topbot",options="header"] -|====================================== -| Char |ASCII |Decimal |Bits -|"0" | 48 | 0 |000000 -|"1" | 49 | 1 |000001 -|"2" | 50 | 2 |000010 -|"3" | 51 | 3 |000011 -|"4" | 52 | 4 |000100 -|"5" | 53 | 5 |000101 -|"6" | 54 | 6 |000110 -|"7" | 55 | 7 |000111 -|"8" | 56 | 8 |001000 -|"9" | 57 | 9 |001001 -|":" | 58 |10 |001010 -|";" | 59 |11 |001011 -|"<" | 60 |12 |001100 -|"=" | 61 |13 |001101 -|">" | 62 |14 |001110 -|"?" | 63 |15 |001111 -|"@" | 64 |16 |010000 -|"A" | 65 |17 |010001 -|"B" | 66 |18 |010010 -|"C" | 67 |19 |010011 -|"D" | 68 |20 |010100 -|"E" | 69 |21 |010101 -|"F" | 70 |22 |010110 -|"G" | 71 |23 |010111 -|"H" | 72 |24 |011000 -|"I" | 73 |25 |011001 -|"J" | 74 |26 |011010 -|"K" | 75 |27 |011011 -|"L" | 76 |28 |011100 -|"M" | 77 |29 |011101 -|"N" | 78 |30 |011110 -|"O" | 79 |31 |011111 -|"P" | 80 |32 |100000 -|"Q" | 81 |33 |100001 -|"R" | 82 |34 |100010 -|"S" | 83 |35 |100011 -|"T" | 84 |36 |100100 -|"U" | 85 |37 |100101 -|"V" | 86 |38 |100110 -|"W" | 87 |39 |100111 -|"`" | 96 |40 |101000 -|"a" | 97 |41 |101001 -|"b" | 98 |42 |101010 -|"c" | 99 |43 |101011 -|"d" |100 |44 |101100 -|"e" |101 |45 |101101 -|"f" |102 |46 |101110 -|"g" |103 |47 |101111 -|"h" |104 |48 |110000 -|"i" |105 |49 |110001 -|"j" |106 |50 |110010 -|"k" |107 |51 |110011 -|"l" |108 |52 |110100 -|"m" |109 |53 |110101 -|"n" |110 |54 |110110 -|"o" |111 |55 |110111 -|"p" |112 |56 |111000 -|"q" |113 |57 |111001 -|"r" |114 |58 |111010 -|"s" |115 |59 |111011 -|"t" |116 |60 |111100 -|"u" |117 |61 |111101 -|"v" |118 |62 |111110 -|"w" |119 |63 |111111 -|====================================== - -Concatenate all six-bit quantities found in the payload, MSB first. -This is the binary payload of the sentence. - -== AIS Payload Data Types == - -Data in AIS message payloads (what you get after undoing the AIVDM/AIVDO -armoring) is encoded as bitfields in the sentence. Bitfields may be -interpreted in one of the following ways: - -- Signed or unsigned integer -- Float (scaled from signed integer) -- Flag or Boolean -- Index into a controlled vocabulary -- Reserved bits -- Spare bits -- Strings - -Numeric bitfields are interpreted as big-endian twos-complement -integers; when signed, the sign bit is the highest. - -Float fields have an associated divisor which should be applied -to convert to the correct units. In one case, the ROT field in message -types 1-3, the scaling operation involves a more elaborate formula. - -Flags are encoded as 1 for true/yes/on, 0 for false/no/off. - -Indices into controlled vocabularies are numeric bitfields which -must be interpreted using per-field string lists specified in the -standards. - -Spare fields generally seem to have been inserted in order to put -certain field starts on 8-bit boundaries, and should be ignored. Decoders -should not, however, assume that spare fields will be all zeroes. - -Reserved fields should not be ignored, as they may be assigned for -extension data in minor revisions of the AIS standard; it is noted in -the message descriptions where this has already occurred. It is good -practice for a decoder to make reserved fields available to client -applications as uninterpreted bitfields. - -Character-string fields within AIS messages are encoded in a special -way, referred to as "six-bit" in the tables below. First, chop the -string field into consecutive six-bit nibbles without padding (each -span of three 8-bit bytes includes 4 of these). Each six-bit nibble -maps to an ASCII character. Nibbles 0-31 map to the characters "@" ( -ASCII 64) through "\_" (ASCII 95) respectively; nibbles 32-63 map to -characters " " (ASCII 32) though "?" (ASCII 63). Lowercase ASCII -letters, the backtick, right and left curly brackets, pipe bar, tilde -and DEL cannot be encoded. - -.Sixbit ASCII -[width="25%",frame="topbot"] -|========================================================================================== -|000000 | 0 |"@" |010000 |16 |"P" |100000 |32 |" " |110000 |48 |"0" -|000001 | 1 |"A" |010001 |17 |"Q" |100001 |33 |"!" |110001 |49 |"1" -|000010 | 2 |"B" |010010 |18 |"R" |100010 |34 |""" |110010 |50 |"2" -|000011 | 3 |"C" |010011 |19 |"S" |100011 |35 |"\#" |110011 |51 |"3" -|000100 | 4 |"D" |010100 |20 |"T" |100100 |36 |"$" |110100 |52 |"4" -|000101 | 5 |"E" |010101 |21 |"U" |100101 |37 |"%" |110101 |53 |"5" -|000110 | 6 |"F" |010110 |22 |"V" |100110 |38 |"&" |110110 |54 |"6" -|000111 | 7 |"G" |010111 |23 |"W" |100111 |39 |"\'" |110111 |55 |"7" -|001000 | 8 |"H" |011000 |24 |"X" |101000 |40 |"(" |111000 |56 |"8" -|001001 | 9 |"I" |011001 |25 |"Y" |101001 |41 |")" |111001 |56 |"9" -|001010 |10 |"J" |011010 |26 |"Z" |101010 |42 |"\*" |111010 |58 |":" -|001011 |11 |"K" |011011 |27 |"[" |101011 |43 |"\+" |111011 |59 |";" -|001100 |12 |"L" |011100 |28 |"{backslash}" |101100 |44 |"," |111100 |60 |"<" -|001101 |13 |"M" |011101 |29 |"]" |101101 |45 |"-" |111101 |61 |"=" -|001110 |14 |"N" |011110 |30 |"\^" |101110 |46 |"." |111110 |62 |">" -|001111 |15 |"O" |011111 |31 |"\_" |101111 |47 |"/" |111111 |63 |"?" -|========================================================================================== - -According to the standard, trailing unused characters in six-bit -fields will be represented by "@" (six-bit zero); however, real-world -encoders are not careful about this and often have nonzero garbage -after the "@". The terminating "@" should not be considered part of -the text, and any non-"@" characters after it should be discarded. It -is also common to space-fill short fields such as ship and station -name, so a decoder should strip trailing spaces after stripping -at-signs and the garbage after them. - -Trailing string fields are often specified as "up to" a certain number of bits. -Decoders should be prepared to handle any field length up to that -number, including zero. - -== AIS Payload Interpretation == - -The following table describes message types that are international -standards from <> and its revisions. There are also local -and regional extensions used on inland waterways such as the Danube -and the Thames and in British and Irish coastal waters; pointers -to some of these are included later in this document. - -Note that many sources use 1-origin numbering for the bits. We'll -use 0-origin in this document. - -The first 6 bits of the payload (0-5) are the message type. Message -types are as follows: - -.Message types -[width="50%",frame="topbot"] -|====================================================== -|01 |Position Report Class A -|02 |Position Report Class A (Assigned schedule) -|03 |Position Report Class A (Response to interrogation) -|04 |Base Station Report -|05 |Static and Voyage Related Data -|06 |Binary Addressed Message -|07 |Binary Acknowledge -|08 |Binary Broadcast Message -|09 |Standard SAR Aircraft Position Report -|10 |UTC and Date Inquiry -|11 |UTC and Date Response -|12 |Addressed Safety Related Message -|13 |Safety Related Acknowledgement -|14 |Safety Related Broadcast Message -|15 |Interrogation -|16 |Assignment Mode Command -|17 |DGNSS Binary Broadcast Message -|18 |Standard Class B CS Position Report -|19 |Extended Class B Equipment Position Report -|20 |Data Link Management -|21 |Aid-to-Navigation Report -|22 |Channel Management -|23 |Group Assignment Command -|24 |Static Data Report -|25 |Single Slot Binary Message, -|26 |Multiple Slot Binary Message With Communications State -|27 |Position Report For Long-Range Applications -|====================================================== - -In normal operation, an AIS transceiver will broadcast a position report -(type 1, 2, or 3) every 2 to 10 seconds depending on the vessel's -speed while underway, and every 3 minutes while the vessel is at -anchor and stationary. It will send a type 5 identification every 6 -minutes. (More detail is at <>, part 2.3) - -Class 6 is used for unencrypted structured extension messages systems -conforming to the Inland AIS standard defined by <>, and by local -authorities such as the St. Lawrence Seaway and the U.S Coast Guard's -PAWSS. This document describes all of the Class 6 special message -formats approved for use in <>, <>, and <>. - -Class 8 is in common use for private encrypted messages, such as -location transmission in military exercises. It is also used for -unencrypted structured extension messages by Inland AIS, and by local -authorities such as the St. Lawrence Seaway and PAWSS. This document -describes all of the Class 8 special message formats approved for use -in <>, <>, and <>. - -Classes 12 and 14 are used for text messaging, nominally safety-related -but also for traffic control and occasionally chatter. - -In practice, message types other than 1, 3, 4, 5, 18, and 24 are -unusual or rare; many AIS transmitters never emit them. - -An MMSI is a Mobile Marine Service Identifier, a unique 9-digit ID for -the ship's radio(s). The first three digits convey information about -the country in which the ID was issued <>. US vessels -travelling solely in U.S. waters sometimes incorrectly omit the -leading "3", the geography code for North and Central America and -Caribbean, emitting 8-digit MMSIs beginning with the U.S. country code -of 669. - -According to <>, different formats of MMSI are used for -different classes of transmitter. In the format descriptions below, a -MID is a three-digit decimal literal ranging from 201 to 775 that -identifies a country or other maritime jurisdiction. See <> -for a list of MIDs. - -.MID formats -[frame="topbot",options="header"] -|============================================================================== -|8MIDXXXXX | Diver's radio (not used in the U.S. in 2013) -|MIDXXXXXX | Ship -|0MIDXXXXX | Group of ships; the U.S. Coast Guard, for example, is 03699999 -|00MIDXXXX | Coastal stations -|111MIDXXX | SAR (Search and Rescue) aircraft -|99MIDXXXX | Aids to Navigation -|98MIDXXXX | Auxiliary craft associated with a parent ship -|970MIDXXX | AIS SART (Search and Rescue Transmitter) -|972XXXXXX | MOB (Man Overboard) device -|974XXXXXX | EPIRB (Emergency Position Indicating Radio Beacon) AIS -|============================================================================== - -Detailed descriptions of message types 1-24 follow. Message types 1-22 -are derived from <>. Message type 23 was described to me by Mike -Greene based on <>. Message type 24 was described to me by -<>, whose Python toolkit decodes it. Message types 25-26 are -reported by <>, who observes they were added in Version 3 of -<>. Message type 27 is direct from <> version 4. - -The "Member" column in these tables is not derived from any of the ITU -standards or amendments. I have invented it in order to be able to -describe a lossless textual encoding of AIS sentences in JSON. These -names are also chosen for suitability as structure/object member names -in computer languages, so that application programming interfaces -across different languages can have a common and readily intelligible -set to use. - -The "T" column declares the data type of the field, and may have -any of the values in the following table. It is intended to be used -for generating bitfield-extraction code directly from the message -type descriptions. - -[frame="topbot",options="header"] -|============================================================================== -|u| Unsigned integer -|U| Unsigned integer with scale - renders as float, suffix is decimal places -|i| Signed integer -|I| Signed integer with scale - renders as float, suffix is decimal places -|b| Boolean -|e| Enumerated type (controlled vocabulary) -|x| Spare or reserved bit -|t| String (packed six-bit ASCII) -|d| Data (uninterpreted binary) -|a| Array boundary, numeric suffix is maximum array size. - ^ before suffix means preceding fields is the length. - Following fields are repeated to end of message -|============================================================================== - -The field breakdowns in this document have been checked against live -decoded data rendered by known-good implementations for message types -1-15, 18-21, and 24. Described but unchecked are 16-17, 22-23, and -25-27. Also, the interpretation of IMO extension subtypes of messages -6 and 8 has yet to be tested. - -Bit lengths and length ranges are given because decoders should check -them against the message type. Messages with correct checksums but the -wrong payload length for their type occur with about 0.3% frequency on -AISHub; if you don't reject these, your clients will see spurious -zeros or garbage. - -=== Types 1, 2 and 3: Position Report Class A === - -Type 1, 2 and 3 messages share a common reporting structure for -navigational information; we'll call it the Common Navigation Block -(CNB). This is the information most likely to be of interest for -decoding software. Total of 168 bits, occupying one AIVDM sentence. - -//: Type CNB -.Common Navigation Block -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 1-3 -|6-7 | 2 |Repeat Indicator |repeat |u|Message repeat count -|8-37 |30 |MMSI |mmsi |u|9 decimal digits -|38-41 | 4 |Navigation Status |status |e|See "Navigation Status" -|42-49 | 8 |Rate of Turn (ROT) |turn |I3|See below -|50-59 |10 |Speed Over Ground (SOG) |speed |U1|See below -|60-60 | 1 |Position Accuracy |accuracy |b|See below -|61-88 |28 |Longitude |lon |I4|Minutes/10000 (see below) -|89-115 |27 |Latitude |lat |I4|Minutes/10000 (see below) -|116-127 |12 |Course Over Ground (COG)|course |U1|Relative to true north, - to 0.1 degree precision -|128-136 | 9 |True Heading (HDG) |heading |u|0 to 359 degrees, - 511 = not available. -|137-142 | 6 |Time Stamp |second |u|Second of UTC timestamp -|143-144 | 2 |Maneuver Indicator |maneuver |e|See "Maneuver Indicator" -|145-147 | 3 |Spare | |x|Not used -|148-148 | 1 |RAIM flag |raim |b|See below -|149-167 |19 |Radio status |radio |u|See below -|============================================================================== - -The Repeat Indicator is a directive to an AIS transceiver that this -message should be rebroadcast. This was intended as a way of getting -AIS messages around hills and other obstructions in coastal waters, -but is little used as base station coverage is more effective. It is -intended that the bit be incremented on each retransmission, to a -maximum of three hops. A value of 3 indicates "Do not repeat". - -.Navigation Status -[width="50%",frame="topbot"] -|================================================================= -|0 | Under way using engine -|1 | At anchor -|2 | Not under command -|3 | Restricted manoeuverability -|4 | Constrained by her draught -|5 | Moored -|6 | Aground -|7 | Engaged in Fishing -|8 | Under way sailing -|9 | Reserved for future amendment of Navigational Status for HSC -|10| Reserved for future amendment of Navigational Status for WIG -|11| Reserved for future use -|12| Reserved for future use -|13| Reserved for future use -|14| AIS-SART is active -|15| Not defined (default) -|================================================================= - -Note, the AIS-SART value was added after <> and designates an -AIS transmitter in an survival craft such as a lifeboat. See -<> for the field specification and <> for -background. - -Turn rate is encoded as follows: - -* 0 = not turning -* 1...126 = turning right at up to 708 degrees per minute or higher -* 1...-126 = turning left at up to 708 degrees per minute or higher -* 127 = turning right at more than 5deg/30s (No TI available) -* -127 = turning left at more than 5deg/30s (No TI available) -* 128 (80 hex) indicates no turn information available (default) - -Values between 0 and 708 degrees/min coded by ROT~AIS~=4.733 * -SQRT(ROT~sensor~) degrees/min where ROT~sensor~ is the Rate of Turn as -input by an external Rate of Turn Indicator. ROT~AIS~ is rounded to -the nearest integer value. Thus, to decode the field value, divide by 4.733 -and then square it. Sign of the field value should be preserved when -squaring it, otherwise the left/right indication will be lost. - -Speed over ground is in 0.1-knot resolution from 0 to 102 knots. -Value 1023 indicates speed is not available, value 1022 indicates -102.2 knots or higher. - -The position accuracy flag indicates the accuracy of the fix. A value of -1 indicates a DGPS-quality fix with an accuracy of < 10ms. 0, the -default, indicates an unaugmented GNSS fix with accuracy > 10m. - -Longitude is given in in 1/10000 min; divide by 600000.0 to obtain -degrees. Values up to plus or minus 180 degrees, East = positive, West -\= negative. A value of 181 degrees (0x6791AC0 hex) indicates that -longitude is not available and is the default. - -Latitude is given in in 1/10000 min; divide by 600000.0 to obtain -degrees. Values up to plus or minus 90 degrees, North = positive, -South = negative. A value of 91 degrees (0x3412140 hex) indicates -latitude is not available and is the default. - -Course over ground will be 3600 (0xE10) if that data is not available. - -Seconds in UTC timestamp should be 0-59, except for these special values: - -* 60 if time stamp is not available (default) -* 61 if positioning system is in manual input mode -* 62 if Electronic Position Fixing System operates in estimated (dead - reckoning) mode, -* 63 if the positioning system is inoperative. - -The Regional Reserved field is intended for use by local maritime -authorities. It is not known to be in any actual use up to 2009. - -The Maneuver Indicator (143-144) may have these values: - -.Maneuver Indicator -[width="50%",frame="topbot",options="header"] -|=========================================================== -|0 | Not available (default) -|1 | No special maneuver -|2 | Special maneuver (such as regional passing arrangement) -|=========================================================== - -Riverine and inland navigation systems conforming to <> -designate this field "Blue Sign" with the following enumerated -values: - -.Blue Sign -[width="50%",frame="topbot",options="header"] -|=========================================================== -|0 | Not available (default) -|1 | No -|2 | Yes -|=========================================================== - -The interpretation of bits 143-147 has been a bit unstable. In -<> and therefore in the original <>, they were -described like this: - -[width="50%",frame="topbot",options="header"] -|================================= -|Field |Len |Description -|143-145 | 3 |Regional Reserved -|146-147 | 2 |Spare -|================================= - -The interpretation of 143-144 as a special maneuver field is new in -revision 3 of <>. - -The RAIM flag indicates whether Receiver Autonomous Integrity -Monitoring is being used to check the performance of the EPFD. -0 = RAIM not in use (default), 1 = RAIM in use. See <> for -a detailed description of this flag. - -Bits 149-167 are diagnostic information for the radio system. Consult -<> for detailed description of the latter. - -=== Type 4: Base Station Report === - -This message is to be used by fixed-location base stations to -periodically report a position and time reference. Total of 168 bits, -occupying one AIVDM sentence. - -The standard uses "EPFD" to designate any Electronic Position Fixing Device. - -//: Type 4 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 4 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |MMSI |mmsi |u|9 decimal digits -|38-51 | 14 |Year (UTC) |year |u|UTC, 1-9999, 0 = N/A (default) -|52-55 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) -|56-60 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|61-65 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|66-71 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|72-77 | 6 |Second (UTC) |second |u|0-59; 60 = N/A (default) -|78-78 | 1 |Fix quality |accuracy |b|As in Common Navigation Block -|79-106 | 28 |Longitude |lon |I4|As in Common Navigation Block -|107-133 | 27 |Latitude |lat |I4|As in Common Navigation Block -|134-137 | 4 |Type of EPFD |epfd |e|See "EPFD Fix Types" -|138-147 | 10 |Spare | |x|Not used -|148-148 | 1 |RAIM flag |raim |b|As for common navigation block -|149-167 | 19 |SOTDMA state |radio |u|As in same bits for Type 1 -|============================================================================== - -.EPFD Fix Types -[width="50%",frame="topbot",options="header"] -|=================================== -|Code |Position Fix Type -|0 |Undefined (default) -|1 |GPS -|2 |GLONASS -|3 |Combined GPS/GLONASS -|4 |Loran-C -|5 |Chayka -|6 |Integrated navigation system -|7 |Surveyed -|8 |Galileo -|=================================== - -Note: though values 9-15 are marked "not used" in <>, the EPFD -type value 15 (all field bits 1) is not uncommon in the wild; it -appears some receivers emit it as the undefined value. Decoders should -be prepared to accept this. - -=== Type 5: Static and Voyage Related Data === - -Message has a total of 424 bits, occupying two AIVDM sentences. - -In practice, the information in these fields (especially ETA and -destination) is not reliable, as it has to be hand-updated by -humans rather than gathered automatically from sensors. - -Also note that it is fairly common in the wild for this message to -have a wrong bit length (420 or 422). Robust decoders should ignore -trailing garbage and deal gracefully with a slightly truncated -destination field. - -//: Type 5 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member/Type |T|Encoding -|0-5 | 6 |Message Type |type |u|Constant: 5 -|6-7 | 2 |Repeat Indicator |repeat |u|Message repeat count -|8-37 | 30 |MMSI |mmsi |u|9 digits -|38-39 | 2 |AIS Version |ais_version |u|0=<>, - 1-3 = future editions -|40-69 | 30 |IMO Number |imo |u|IMO ship ID number -|70-111 | 42 |Call Sign |callsign |t|7 six-bit characters -|112-231 |120 |Vessel Name |shipname |t|20 six-bit characters -|232-239 | 8 |Ship Type |shiptype |e|See "Codes for Ship Type" -|240-248 | 9 |Dimension to Bow |to_bow |u|Meters -|249-257 | 9 |Dimension to Stern |to_stern |u|Meters -|258-263 | 6 |Dimension to Port |to_port |u|Meters -|264-269 | 6 |Dimension to Starboard |to_starboard |u|Meters -|270-273 | 4 |Position Fix Type |epfd |e|See "EPFD Fix Types" -|274-277 | 4 |ETA month (UTC) |month |u|1-12, 0=N/A (default) -|278-282 | 5 |ETA day (UTC) |day |u|1-31, 0=N/A (default) -|283-287 | 5 |ETA hour (UTC) |hour |u|0-23, 24=N/A (default) -|288-293 | 6 |ETA minute (UTC) |minute |u|0-59, 60=N/A (default) -|294-301 | 8 |Draught |draught |U1|Meters/10 -|302-421 |120 |Destination |destination |t|20 6-bit characters -|422-422 | 1 |DTE |dte |b|0=Data terminal ready, - 1=Not ready (default). -|423-423 | 1 |Spare | |x|Not used -|============================================================================== - -<> specifies the following: - -* the IMO Number field should be zeroed for inland vessels. -* ATIS code should be used for inland vessels -* ship dimensions should be set to the maximum rectangle size of the convoy -* draught information should be rounded up to nearest decimeter -* For the destination, UN/LOCODE and ERI terminal codes should be used - -Ship dimensions will be 0 if not available. For the dimensions to bow -and stern, the special value 511 indicates 511 meters or greater; for -the dimensions to port and starboard, the special value 63 indicates -63 meters or greater. - -.Codes for Ship Type -[width="50%",frame="topbot",options="header"] -|============================================================== -|Code |Ship & Cargo Classification -|0 |Not available (default) -|1-19 |Reserved for future use -|20 |Wing in ground (WIG), all ships of this type -|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), all ships of this type -|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, all ships of this type -|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, all ships of this type -|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, all ships of this type -|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, all ships of this 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 -|============================================================== - -Note that garbage values greater than 99 are supposed to be unused, -but are not uncommon in the wild; AIS transmitters seem prone to put -junk in this field when it's not explicitly set. Decoders should -treat these like value 0 rather than throwing an exception until and -unless the controlled vocabulary is extended to include the unknown -values. - -=== Type 6: Binary Addressed Message === - -Message type 6 is an addressed point-to-point message with unspecified -binary payload. The St. Lawrence Seaway AIS system, the USG PAWSS -system, and the Port Authority of London use this payload for local -extension messages. <> and <> describe payload use as -international extension messages. This type is variable in length up -to a maximum of 1008 bits (up to 5 AIVDM sentence payloads). - -//: Type 6 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default) - 1 = retransmitted -|71 | 1 |Spare | |x|Not used -|72-81 | 10 |Designated Area Code |dac |u|Unsigned integer -|82-87 | 6 |Functional ID |fid |u|Unsigned integer -|88 |920 |Data |data |d|Binary data - May be shorter than 920 bits. -|============================================================================== - -Interpretation of the binary payload is controlled by: - -* The Designated Area Code, which is a jurisdiction code: 366 for the - United States. It uses the same encoding as the area designator in - MMMSIs; see <>. 1 designates international (ITU) messages. - -* The FID, which is the Functional ID for a message subtype. In some - sources this is abbreviated FI. - -The following is a non-exhaustive list of standardized DAC-FID pairs -in use for type 6. - -|============================================================================== -| DAC |FID | Source | Status | Description -| 1 | 12 | <> | Deprecated | Dangerous cargo indication -| 1 | 14 | <> | Deprecated | Tidal window -| 1 | 16 | <> | Deprecated/In Use| Number of persons on board -| 1 | 16 | <> | Standard | Number of persons on board -| 1 | 18 | <> | Standard | Clearance time to enter port -| 1 | 20 | <> | Standard | Berthing data (addressed) -| 1 | 23 | <> | In use | Area notice (addressed) -| 1 | 25 | <> | Standard | Dangerous Cargo indication -| 1 | 28 | <> | Standard | Route info addressed -| 1 | 30 | <> | Standard | Text description addressed -| 1 | 32 | <> | Standard | Tidal Window -| 200 | 21 | <> | Standard | ETA at lock/bridge/terminal -| 200 | 22 | <> | Standard | RTA at lock/bridge/terminal -| 200 | 55 | <> | Standard | Number of persons on board -| 235 | 10 | <> | In use | AtoN monitoring data (UK) -| 250 | 10 | <> | In use | AtoN monitoring data (ROI) -|============================================================================== - -DAC/FID pairs are assigned separately per message type. - -Note that the apparent presence of one of these DAC/FID pairs does -not guarantee that the message is structured. Decoders should -perform range validation on the structured fields and interpret the -message as unstructured if any check fails. (As of Aug 2014 no such -collisions have been in the wild; but see the parallel note for Type 8.) - -A list of binary layouts for selected subtypes of message 6 follows. - -==== IMO236 Dangerous Cargo Indication ==== - -This message should be used as a response to a request for Dangerous -Cargo Indication from a competent authority. The message content is -used to identify the port where the documents for the dangerous goods -cargo can be found, e. g. last and next port of call, and to allow -the requesting authority to form a danger estimate. - -A message 6 subtype. DAC = 001 FID = 12. Fixed length: 360 bits. -This is the <> version, now deprecated; there is a later -<> version. - -//: Type 6(1/12) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit|u|0 = no retransmit (default), - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 12 -|88-117 | 30 |Last Port Of Call |lastport |t|5 6-bit characters, UN locode -|118-121 | 4 |ETA month (UTC) |lmonth |u|1-12, 0=N/A (default) -|122-126 | 5 |ETA day (UTC) |lday |u|1-31, 0=N/A (default) -|127-131 | 5 |ETA hour (UTC) |lhour |u|0-23, 24=N/A (default) -|132-137 | 6 |ETA minute (UTC) |lminute |u|0-59, 60=N/A (default) -|138-167 | 30 |Next Port Of Call |nextport |t|5 6-bit characters, UN locode -|168-171 | 4 |ETA month (UTC) |nmonth |u|1-12, 0=N/A (default) -|172-176 | 5 |ETA day (UTC) |nday |u|1-31, 0=N/A (default) -|177-181 | 5 |ETA hour (UTC) |nhour |u|0-23, 24=N/A (default) -|182-187 | 6 |ETA minute (UTC) |nminute |u|0-59, 60=N/A (default) -|188-307 |120 |Main Dangerous Good |dangerous |t|20 6-bit characters -|308-331 | 24 |IMD Category |imdcat |t|4 6-bit characters -|332-344 | 13 |UN Number |unid |u|1-3363 UN Number -|345-354 | 10 |Amount of Cargo |amount |u|Unsigned integer -|355-356 | 2 |Unit of Quantity |unit |e|See "Cargo Unit Codes" -|357-359 | 3 |Spare | |x|Not used -|============================================================================== - -.Cargo Unit Codes -[width="50%",frame="topbot",options="header"] -|=================================== -|Code |Unit -|0 |Not available (default) -|1 |kg -|2 |metric tons -|3 |metric kilotons -|=================================== - -==== IMO236 Tidal Window ==== - -This message should be used by shore stations to inform vessels about -tidal windows which allow a vessel the safe passage of a fairway. The -message includes 1-3 predictions of current speed and current direction. -Acknowledgment is required. - -A message 6 subtype. DAC = 001 FID = 14. Variable length: 190-376 bits -This is the <> version; there is an <> version with -different widths for the latitude, longitude, and current-speed fields -(also the order of lat/lon is swapped). - -//: Type 6(1/14) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|See Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default), - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 14 -|88-91 | 4 |Month |month |u|1-12; 0 = N/A (default) -|92-96 | 5 |Day |day |u|1-31; 0 = N/A (default) -|97 | | |tidals |a3|Tidal information array -|0-26 | 27 |Latitude |lat |I4|Unit = minutes * 0.0001, - 91000 = N/A (default), - N positive, S negative. -|27-54 | 28 |Longitude |lon |I4|Unit = minutes * 0.0001, - 181000 = N/A (default), - E positive, W negative. -|55-59 | 5 |From UTC Hour |from_hour |u|0-23, 24 = N/A (default) -|60-65 | 6 |From UTC Minute |from_min |u|0-59, 60 = N/A (default) -|66-70 | 5 |To UTC Hour |to_hour |u|0-23, 24 = N/A (default) -|71-76 | 6 |To UTC Minute |to_min |u|0-59, 60 = N/A (default) -|77-85 | 9 |Current Dir. Predicted |cdir |u|0-359 deg, 360-N/A (default) -|86-92 | 7 |Current Speed Predicted|cspeed |U1|0-126, units of 0.1 knots, - 127 = N/A (default). -|============================================================================= - -The group of fields from longitude on may repeat twice more to convey up to -three points of tidal information. - -==== IMO236 Number of persons on board ==== - -This message should be used by a ship to report the number of persons -on board, e.g. on request by a competent authority. Acknowledgement -required. - -A message 6 subtype. DAC = 001 FID = 16. - -<> describes a fixed-length, 72-bit message with this layout: - -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 16 -|55-68 | 14 |# persons on board |persons |u|Unsigned integer - 0 = N/A (default) - 8191 = >= 8191 persons. -|69-71 | 3 |Spare | |x|Not used -|============================================================================== - -OPEN-QUESTION: Note that though this is a message 6 subtype and -described in <> with the attribute "addressed", there is no -destination address. A strikeout in <> suggests that this was -originally a subtype of 8. It would be good defensive implementation -for a decoder to accept either. Bit length may be used to distinguish -them. - -<> describes a fixed-length, 136-bit message with this layout: - -//: Type 6(1/16) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default), - 1 = retransmitted. -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 16 -|88-100 | 13 |# persons on board |persons |u|Unsigned integer, - 0 = N/A (default), - 8191 = >= 8191 persons. -|101-135 | 35 |Spare | |x|Not used -|============================================================================== - -==== IMO289 Clearance Time To Enter Port ==== - -This message provides specific ships with information on the port to call and -time to enter. It should be transmitted by an authority competent to grant -use of the port. - -A message 6 subtype. DAC = 001 FID = 18. Fixed length: 360 bits. - -//: Type 6(1/18) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit |b|0 = no retransmit (default), - 1 = retransmitted. -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 18 -|88-97 | 10 |Message Linkage ID |linkage |u|Unsigned integer -|98-101 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) -|102-106 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|107-111 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|112-117 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|118-237 |120 |Name of Port & Berth |portname |t|20 6-bit characters -|238-267 | 30 |Destination |destination|t|5 6-bit characters -|268-292 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, - 181000 = N/A (default). -|293-316 | 24 |Latitude |lat |I3|Unit = minutes * 0.001, - 91000 = N/A (default). -|317-359 | 43 |Spare | |x|Not used -|============================================================================== - -==== IMO 289 Berthing Data (addressed) ==== - -This message provides information on the ship's berth. If sent from a -ship it is a berthing request; if it is transmitted by a competent -authority it is a berthing assignment. - -A message 6 subtype. DAC = 001 FID = 20. Fixed Length: 360 bits. - -The 2-bit fields after "availability" describe services which may be -available at the berth. They are valid only if this master availability -bit is on. - -//: Type 6(1/20) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member/Type |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit |b|0 = no retransmit (default) - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|AC = 001 -|82-87 | 6 |FID |fid |u|ID = 20 -|88-97 | 10 |Message Linkage ID |linkage |u|Unsigned integer -|98-106 | 9 |Berth length |berth_length|u|In 1m steps, 1-510m, - 511 = >= 511m - 0 = N/A (default). -|107-114 | 8 |Berth Water Depth |berth_depth |U1|0.1-25.4m in 0.1 steps - 255 = >= 25.5m - 0 = N/A (default) -|115-117 | 3 |Mooring Position |position |e|See "Mooring Position" -|118-121 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) -|122-126 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|127-131 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|132-137 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|138-138 | 1 |Services Availability|availability|b|0 = services unknown (default) - 1 = services known -|139-140 | 2 |Agent |agent |e|See "Service Status" -|141-142 | 2 |Bunker/fuel |fuel |e|See "Service Status" -|143-144 | 2 |Chandler |chandler |e|See "Service Status" -|145-146 | 2 |Stevedore |stevedore |e|See "Service Status" -|147-148 | 2 |Electrical |electrical |e|See "Service Status" -|149-150 | 2 |Potable water |water |e|See "Service Status" -|151-152 | 2 |Customs house |customs |e|See "Service Status" -|153-154 | 2 |Cartage |cartage |e|See "Service Status" -|155-156 | 2 |Crane(s) |crane |e|See "Service Status" -|157-158 | 2 |Lift(s) |lift |e|See "Service Status" -|159-160 | 2 |Medical facilities |medical |e|See "Service Status" -|161-162 | 2 |Navigation repair |navrepair |e|See "Service Status" -|163-164 | 2 |Provisions |provisions |e|See "Service Status" -|165-166 | 2 |Ship repair |shiprepair |e|See "Service Status" -|167-168 | 2 |Surveyor |surveyor |e|See "Service Status" -|169-170 | 2 |Steam |steam |e|See "Service Status" -|171-172 | 2 |Tugs |tugs |e|See "Service Status" -|173-174 | 2 |Waste disposal (solid) |solidwaste |e|See "Service Status" -|175-176 | 2 |Waste disposal (liquid) |liquidwaste |e|See "Service Status" -|177-178 | 2 |Waste disposal (hazardous)|hazardouswaste|e|See "Service Status" -|179-180 | 2 |Reserved ballast exchange |ballast |e|See "Service Status" -|181-182 | 2 |Additional services|additional |e|See "Service Status" -|183-184 | 2 |Regional reserved 1|regional1 |e|See "Service Status" -|185-186 | 2 |Regional reserved 2|regional2 |e|See "Service Status" -|187-188 | 2 |Reserved for future|future1 |e|See "Service Status" -|189-190 | 2 |Reserved for future|future2 |e|See "Service Status" -|191-310 |120 |Name of Berth |berth_name |t|20 6-bit characters -|311-335 | 25 |Longitude |berth_lon |I3|Minutes * 0.001, - 181000 = N/A (default) -|336-359 | 24 |Latitude |berth_lat |I3|Minutes * 0.001, - 91000 = N/A (default) -|============================================================================== - -The UTC timestamp refers to the time requested or granted for berthing. - -The longitude and latitude refer to the center of the berth. - -.Mooring Position -[width="50%",frame="topbot",options="header"] -|=================================== -|Code |Position -|0 |Not available (default) -|1 |Port-side to -|2 |Starboard-side to -|3 |Mediterranean (end-on) mooring -|4 |Mooring buoy -|5 |Anchorage -|6-7 |Reserved for future use -|=================================== - -.Service Status -[width="50%",frame="topbot",options="header"] -|============================================================================= -|Code |Meaning -|0 |Not available or requested (default) -|1 |Service available -|2 |No data or unknown -|3 |Not to be used -|============================================================================= - -==== IMO289 Area Notice (addressed) ==== - -This should be used to convey time- and location-dependent information about -hazards to navigation. For information-lifetime restrictions and usage -guidance, refer to <>. - -A message 6 subtype. DAC = 001 FID = 23. 230 to 1013 bits. There is a -related Message 8 subtype for broadcast use. - -The message consists of a fixed-length header of 143 bits, followed by 1 to -10 sub-area indications which are fixed-length records 87 bits long. Here -is the message header format: - -//: Type 6(1/23) -.Area Notice (addressed) message header -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit |b|0 = no retransmit (default), - 1 = retransmitted. -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 23 -|88-97 | 10 |Message Linkage ID |linkage |u|Unsigned integer -|98-104 | 7 |Notice Description |notice |e|See "Area Notice Description" -|105-108 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) -|109-113 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|114-118 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|119-124 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|125-142 | 18 |Duration |duration |In minutes, - 262143 = N/A (default), - 0 = cancel this notice. -|143 | | |subarea |a10|Subarea array -|0-2 | 2 | |shape |u|Subarea shape -|3-86 | 85 |Subarea Payload |payload |d|Subarea payload -|============================================================================== - -The Message Linkage field is, as usual, for linking to a textual explanatory -message sent with the same linkage ID. The standard says that in this context -it has the semantics of being an identifier of or reference to an area. - -Notice description types are as follows: - -.Area Notice Description -[frame="topbot",options="header"] -|============================================================================== -| 0| Caution Area: Marine mammals habitat -| 1| Caution Area: Marine mammals in area - reduce speed -| 2| Caution Area: Marine mammals in area - stay clear -| 3| Caution Area: Marine mammals in area - report sightings -| 4| Caution Area: Protected habitat - reduce speed -| 5| Caution Area: Protected habitat - stay clear -| 6| Caution Area: Protected habitat - no fishing or anchoring -| 7| Caution Area: Derelicts (drifting objects) -| 8| Caution Area: Traffic congestion -| 9| Caution Area: Marine event -| 10| Caution Area: Divers down -| 11| Caution Area: Swim area -| 12| Caution Area: Dredge operations -| 13| Caution Area: Survey operations -| 14| Caution Area: Underwater operation -| 15| Caution Area: Seaplane operations -| 16| Caution Area: Fishery – nets in water -| 17| Caution Area: Cluster of fishing vessels -| 18| Caution Area: Fairway closed -| 19| Caution Area: Harbor closed -| 20| Caution Area: Risk (define in associated text field) -| 21| Caution Area: Underwater vehicle operation -| 22| (reserved for future use) -| 23| Environmental Caution Area: Storm front (line squall) -| 24| Environmental Caution Area: Hazardous sea ice -| 25| Environmental Caution Area: Storm warning (storm cell or line of storms) -| 26| Environmental Caution Area: High wind -| 27| Environmental Caution Area: High waves -| 28| Environmental Caution Area: Restricted visibility (fog, rain, etc.) -| 29| Environmental Caution Area: Strong currents -| 30| Environmental Caution Area: Heavy icing -| 31| (reserved for future use) -| 32| Restricted Area: Fishing prohibited -| 33| Restricted Area: No anchoring. -| 34| Restricted Area: Entry approval required prior to transit -| 35| Restricted Area: Entry prohibited -| 36| Restricted Area: Active military OPAREA -| 37| Restricted Area: Firing – danger area. -| 38| Restricted Area: Drifting Mines -| 39| (reserved for future use) -| 40| Anchorage Area: Anchorage open -| 41| Anchorage Area: Anchorage closed -| 42| Anchorage Area: Anchorage prohibited -| 43| Anchorage Area: Deep draft anchorage -| 44| Anchorage Area: Shallow draft anchorage -| 45| Anchorage Area: Vessel transfer operations -| 46| (reserved for future use) -| 47| (reserved for future use) -| 48| (reserved for future use) -| 49| (reserved for future use) -| 50| (reserved for future use) -| 51| (reserved for future use) -| 52| (reserved for future use) -| 53| (reserved for future use) -| 54| (reserved for future use) -| 55| (reserved for future use) -| 56| Security Alert - Level 1 -| 57| Security Alert - Level 2 -| 57| Security Alert - Level 3 -| 59| (reserved for future use) -| 60| (reserved for future use) -| 61| (reserved for future use) -| 62| (reserved for future use) -| 63| (reserved for future use) -| 64| Distress Area: Vessel disabled and adrift -| 65| Distress Area: Vessel sinking -| 66| Distress Area: Vessel abandoning ship -| 67| Distress Area: Vessel requests medical assistance -| 68| Distress Area: Vessel flooding -| 69| Distress Area: Vessel fire/explosion -| 70| Distress Area: Vessel grounding -| 71| Distress Area: Vessel collision -| 72| Distress Area: Vessel listing/capsizing -| 73| Distress Area: Vessel under assault -| 74| Distress Area: Person overboard -| 75| Distress Area: SAR area -| 76| Distress Area: Pollution response area -| 77| (reserved for future use) -| 78| (reserved for future use) -| 79| (reserved for future use) -| 80| Instruction: Contact VTS at this point/juncture -| 81| Instruction: Contact Port Administration at this point/juncture -| 82| Instruction: Do not proceed beyond this point/juncture -| 83| Instruction: Await instructions prior to proceeding beyond this point/juncture -| 84| Proceed to this location – await instructions -| 85| Clearance granted – proceed to berth -| 86| (reserved for future use) -| 87| (reserved for future use) -| 88| Information: Pilot boarding position -| 89| Information: Icebreaker waiting area -| 90| Information: Places of refuge -| 91| Information: Position of icebreakers -| 92| Information: Location of response units -| 93| VTS active target -| 94| Rogue or suspicious vessel -| 95| Vessel requesting non-distress assistance -| 96| Chart Feature: Sunken vessel -| 97| Chart Feature: Submerged object -| 98| Chart Feature: Semi-submerged object -| 99| Chart Feature: Shoal area -|100| Chart Feature: Shoal area due north -|101| Chart Feature: Shoal area due east -|102| Chart Feature: Shoal area due south -|103| Chart Feature: Shoal area due west -|104| Chart Feature: Channel obstruction -|105| Chart Feature: Reduced vertical clearance -|106| Chart Feature: Bridge closed -|107| Chart Feature: Bridge partially open -|108| Chart Feature: Bridge fully open -|109| (reserved for future use) -|110| (reserved for future use) -|111| (reserved for future use) -|112| Report from ship: Icing info -|113| (reserved for future use) -|114| Report from ship: Miscellaneous information – define in associated text field -|115| (reserved for future use) -|116| (reserved for future use) -|117| (reserved for future use) -|118| (reserved for future use) -|119| (reserved for future use) -|120| Route: Recommended route -|121| Route: Alternative route -|122| Route: Recommended route through ice -|123| (reserved for future use) -|124| (reserved for future use) -|125| Other – Define in associated text field -|126| Cancellation – cancel area as identified by Message Linkage ID -|127| Undefined (default) -|============================================================================== - -Subarea types are as follows: - -[frame="topbot",options="header"] -|============================================================================== -| 0 | Circle or point -| 1 | Rectangle -| 2 | Sector -| 3 | Polyline -| 4 | Polygon -| 5 | Associated text -| 6-7 | Reserved -|============================================================================== - -Subarea payload layouts are as follows: - -.Circle or Point -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member/Type |T|Units -|0-2 | 3 |Shape of area |shape |e|Constant: 0 -|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions - 1 = meters (default) -|5-29 | 25 |Longitude |lon |I3|Longitude of center point, - Unit = minutes * 0.001, - 181000 = N/A (default). -|30-53 | 24 |Latitude |lat |I3|Latitude of center point, - Unit = minutes * 0.001, - 91000 = N/A (default). -|54-56 | 3 |Precision |precision |u|Decimal places of precision - (defaults to 4) -|57-68 | 12 |Radius |radius |u|Radius of area - 0 = point (default), - else 1-4095 * 10^scale m -|69-86 | 18 |Spare | |x|Not used -|============================================================================== - -.Rectangle -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member/Type |T|Units -|0-2 | 3 |Shape of area |shape |e|Constant: 1 -|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions - 1 = meters (default) -|5-29 | 25 |Longitude |lon |I3|Longitude of SW corner - Unit = minutes * 0.001, - 181000 = N/A (default). -|30-53 | 24 |Latitude |lat |I3|Latitude of SW corner - Unit = minutes * 0.001, - 91000 = N/A (default). -|54-56 | 3 |Precision |precision |u|Decimal places of precision - (defaults to 4) -|57-64 | 8 |E dimension |east |u|Box dimension east - 0 = N/S line (default), - else 1-255 * 10^scale m -|65-72 | 8 |N dimension |north |u|Box dimension north - 0 = E/W line (default), - else 1-255 * 10^scale m -|73-81 | 9 |Orientation |orientation |u|Degrees clockwise from true N, - 0 = no rotation (default), - else 1-359, - 360-511 reserved. -|82-86 | 5 |Spare | |x|Not used -|============================================================================== - -.Sector -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member/Type |T|Units -|0-2 | 3 |Shape of area |shape |e|Constant: 2 -|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions - 1 = meters (default) -|5-29 | 25 |Longitude |lon |I3|Longitude of center point, - Unit = minutes * 0.001, - 181000 = N/A (default). -|30-53 | 24 |Latitude |lat |I3|Latitude of center point, - Unit = minutes * 0.001, - 91000 = N/A (default). -|54-56 | 3 |Precision |precision |u|Decimal places of precision - (defaults to 4) -|57-68 | 12 |Radius |radius |u|Radius of area - 0 = point (default), - else 1-4095 * 10^scale m -|69-77 | 9 |Left boundary |left |u|Degrees clockwise from true N, - 0 = no rotation (default), - else 1-359, - 360-511 reserved. -|78-86 | 9 |Right boundary |right |u|Degrees clockwise from true N, - 0 = no rotation (default), - else 1-359, - 360-511 reserved. -|============================================================================== - -.Polyline -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member/Type |T|Units -|0-2 | 3 |Shape of area |shape |e|Constant: 3 -|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions - 1 = meters (default) -|5 | | |waypoints |a4|Waypoints array -|0-9 |10 |Bearing |bearing |u|True bearing in half-degree - steps from previous waypoint; - 720 = N/A (default). -|10-19 |10 |Distance |distance |u|Distance from prev. waypoint, - 0 = no point (default), - else 1-1023 * 10^scale m -|============================================================================== - -The last two fields are repeated 4 times; the final 2 bits of 87 are -unused. A polyline must be preceded by either (a) a circle, in which -case the first bearing is from the center, or (b) a polyline, in which -case the first bearing is from the implied last point. - -.Polygon -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member/Type |T|Units -|0-2 | 3 |Shape of area |shape |e|Constant: 4 -|3-4 | 2 |Scale factor |scale |u|Exponent for area dimensions - 1 = meters (default) -|5 | | |vertices |a4|Vertices array -|0-9 |10 |Bearing |bearing |u|True bearing in half-degree - steps from previous vertex; - 720 = N/A (default). -|10-19 |10 |Distance |distance |u|Distance from prev. vertex, -|============================================================================== - -The last two fields are repeated 4 times; the final 2 bits of 87 are -unused. A polygon must be preceded by a circle; the first bearing is -from the circle center, which is treated as the zero vertex. There is -an implied boundary from the last polygon vertex to the zero vertex. - -.Associated text -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member/Type |T|Units -|0-2 | 3 |Shape of area |shape |e|Constant: 5 -|3-86 |84 |Text |text |t|14 chars of packed 6-bit. -|============================================================================== - -==== IMO289 Dangerous Cargo Indication ==== - -See the IMO236 variant for the meaning of this message. - -A message 6 subtype. DAC = 001 FID = 25. Variable length: 117-576 bits. -This is the <> version; there is an earlier <> version -with a different layout, deprecated in <>. - -//: Type 6(1/25) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default) - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 25 -|88-89 | 2 |Unit of Quantity |unit |e|See "Cargo Unit Codes" -|90-99 | 10 |Amount of Cargo |amount |u|Unsigned integer - 0 = N/A (default) - 0 = N/A (default) -|100 | | |cargos |a28|Cargo types array -|0-3 | 4 |Cargo code |code |e|See "Cargo Codes" -|4-16 | 13 |Cargo subtype |subtype |u|Unsigned integer - 0 = N/A (default) -|============================================================================== - -The last two fields may repeat to describe up to 28 subcargos. The count -of repetitions must be computed from the message payload length. - -For cargo unit codes, see the description of the IMO236 variant of -this message. - -.Cargo Codes -[width="50%",frame="topbot",options="header"] -|=================================== -|Code |Code under which cargo is carried -|0 |Not available (default) -|1 |IMDG Code (in packed form) -|2 |IGC code -|3 |BC Code (from 1.1.2011 IMSBC) -|4 |MARPOL Annex I List of oils (Appendix 1) -|5 |MARPOL Annex II IBC Code -|6 |Regional use -|7-15 |Reserved for future use -|=================================== - -The subtype field may be interpreted as an IMDG class or division code -(if the cargotype is 1 = IMDG code) or as a UN number (if the -cargotype is 2 = IGC code) or as a pair of BC class and IMDG class (if -the cargotype is 3 = BC code) or as a MARPOL Annex I code (if -the cargotype is 4 = MARPOL Annex I) or as a MARPOL Annex II code (if -the cargotype is 5 = MARPOL Annex II). - -.Dangerous Cargo Indication: MARPOL Annex I list of oils -[width="50%",frame="topbot",options="header"] -|=================================== -|0 | N/A (default) -|1 | asphalt solutions -|2 | oils -|3 | distillates -|4 | gas oil -|5 | gasoline blending stocks -|6 | gasoline -|7 | jet fuels -|8 | naphtha -|9-15 | reserved for future use -|=================================== - -.Dangerous Cargo Indication: MARPOL Annex II list of oils -[width="50%",frame="topbot",options="header"] -|=================================== -|0 | N/A (default) -|1 | Category X -|2 | Category Y -|3 | Category Z -|4 | Other substances -|5-7 | reserved for future use -|=================================== - -==== IMO289 Route Information (addressed) ==== - -The content of this message is a time and a list of waypoints describing a -course. It has a broadcast equivalent that is a message 8 subtype. - -A message 6 subtype. DAC = 001 FID = 28. Variable length: 204-1029 bits. - -//: Type 6(1/28) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmission (default), - 1 = retransmitted. -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 28 -|88-97 | 10 |Message Linkage ID|linkage |u|Unsigned integer -|98-100 | 3 |Sender Class |sender |u|0 = ship (default), - 1 = authority, - 27 = reserved for future use -|101-105 | 5 |Route Type |rtype |e|See "Route Type Codes" -|106-109 | 4 |Start month (UTC) |month |u|1-12, 0=N/A (default) -|110-114 | 5 |Start day (UTC) |day |u|1-31, 0=N/A (default) -|115-119 | 5 |Start hour (UTC) |hour |u|0-23, 24=N/A (default) -|120-125 | 6 |Start minute (UTC)|minute |u|0-59, 60=N/A (default) -|126-143 | 18 |Duration |duration |u|Minutes from start time, - 0 = cancel route, - 262,143 = N/A (default), -|144-148 | 5 | |waycount |u|Waypoint count (1-16), - Values 17-31 are not used. -|149 | | |waypoints |a^16|Waypoint array -|0-27 | 28 |Longitude |lon |I4|Minutes * 0.0001, - 181000 = N/A (default), - E positive, W negative. -|28-54 | 27 |Latitude |lat |I4|Minutes * 0.0001, - 91000 = N/A (default), - N positive, S negative. -|============================================================================== - -The final pair of fields in the table above is a waypoint. The message may -end with 1 to 16 waypoints. - -.Route Type Codes -[width="50%",frame="topbot",options="header"] -|=================================== -|0 |Undefined (default) -|1 |Mandatory -|2 |Recommended -|3 |Alternative -|4 |Recommended route through ice -|5 |Ship route plan -|6-30 |Reserved for future usage -|31 |Cancel route identified by message linkage -|=================================== - -==== IMO289 Text description (addressed) ==== - -This message may be used to attach a text description to another message with -a Message Linkage ID matching this one. It is intended that the combination -of MMSI and Message Linkage ID should be unique. - -A message 6 subtype. DAC = 001 FID = 30. Variable length: 104-1028 bits. - -Intended to be used to associate a text annotation with another message -via the Message Linkage ID field. - -//: Type 6(1/30) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit |u|0 = no retransmit (default), - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 30 -|88-97 | 10 |Message Linkage ID|linkage |u|Unsigned integer -|98-? | 6-930 |Description |description|t|String -|============================================================================== - -There is an equivalent subtype of message 8 that is a broadcast description. - -==== Tidal Window (IMO289) ==== - -See the <> version of this message for intended meaning. - -A message 6 subtype. DAC = 001 FID = 32. Variable length: 186-362 bits. -This is the <> version; there is an <> version with -different bit widths for the latitude and longitude fields. - -//: Type 6(1/32) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit|b|0 = no retransmit (default), - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 001 -|82-87 | 6 |FID |fid |u|FID = 32 -|88-91 | 4 |Month |month |u|1-12; 0 = N/A (default) -|92-96 | 5 |Day |day |u|1-31; 0 = N/A (default) -|97 | | |tidals |a3|Tidal information array -|0-24 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, - 181000 = N/A (default), - E positive, W negative. -|25-48 | 24 |Latitude |lat |I3|Unit = minutes * 0.001. - 91000 = N/A (default), - N positive, S negative. -|49-53 | 5 |From UTC Hour |from_hour |u|0-23, 24 = N/A (default) -|54-59 | 6 |From UTC Minute |from_min |u|0-59, 60 = N/A (default) -|60-64 | 5 |To UTC Hour |to_hour |u|0-23, 24 = N/A (default) -|65-70 | 6 |To UTC Minute |to_min |u|0-59, 60 = N/A (default) -|71-79 | 9 |Current Dir. Predicted |cdir |u|0-359 true bearing, - 360 = N/A (default). -|80-87 | 8 |Current Speed Predicted|cspeed |U1|0-250, units of 0.1 knots, - 251 = speed >= 25.1 knots, - 255 = N/A (default). -|============================================================================= - -The group of fields from longitude on may repeat twice more to convey up to -three points of tidal information. - -==== ETA at lock/bridge/terminal (Inland AIS) ==== - -A message 6 subtype. DAC = 200 FID = 21. Fixed length, 248 bits. - -Should be used by inland vessels only, to send an ETA report to a -lock, bridge or terminal in order to apply for a time slot in resource -planning. - -An acknowledgement by Inland AIS message 22 should be received within -15 minutes. Otherwise, the Inland AIS message 21 should be repeated -once. - -//: Type 6(200/21) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70 | 1 |Retransmit flag |retransmit|u|0 = no retransmit (default), - 1 = retransmitted -|71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 200 -|82-87 | 6 |FID |fid |u|FID = 21 -|88-99 | 12 |UN Country Code |country |t|2 six-bit characters -|100-117 | 18 |UN/LOCODE |locode |t|3 six-bit characters -|118-147 | 30 |Fairway section |section |t|5 six-bit characters -|148-177 | 30 |Terminal code |terminal |t|5 six-bit characters -|178-207 | 30 |Fairway hectometre |hectometre|t|5 six-bit characters -|208-211 | 4 |ETA month |month |u|1-12, 0=N/A (default) -|212-216 | 5 |ETA day |day |u|1-31, 0=N/A (default) -|217-221 | 5 |ETA hour |hour |u|0-23, 24=N/A (default) -|222-227 | 6 |ETA minute |minute |u|0-59, 60=N/A (default) -|228-230 | 3 |Assisting Tugs |tugs |u|0-6, 7 = unknown (default) -|231-242 | 12 |Air Draught |airdraught|u|0-4000 * 0.01m, - 0 = Unknown (default) -|243-247 | 5 |Spare | |x|Not used -|============================================================================== - -<> says of the Destination MMSI field "a virtual MMSI number -should be used for each country, each national AIS network should -route messages addressed to other countries using this virtual MMSI -number". - -OPEN-QUESTION: <> does not specify whether ETA time is UTC -or local. - -==== RTA at lock/bridge/terminal (Inland AIS) ==== - -A message 6 subtype. DAC = 200 FID = 22. Fixed length, 232 bits. - -This message should be sent by base stations only, to assign a RTA at -a lock, bridge or terminal to a certain vessel in response to the -preceding ETA request. - -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit|u|0 = no retransmit (default), - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 200 -|82-87 | 6 |FID |fid |u|FID = 21 -|88-99 | 12 |UN Country Code |country |t|2 six-bit characters -|100-117 | 18 |UN/LOCODE |locode |t|3 six-bit characters -|118-147 | 30 |Fairway section |section |t|5 six-bit characters -|148-177 | 30 |Terminal code |terminal |t|5 six-bit characters -|178-207 | 30 |Fairway hectometre |hectometre|t|5 six-bit characters -|208-211 | 4 |RTA month |month |u|1-12, 0=N/A (default) -|212-216 | 5 |RTA day |day |u|1-31, 0=N/A (default) -|217-221 | 5 |RTA hour |hour |u|0-23, 24=N/A (default) -|222-227 | 6 |RTA minute |minute |u|0-59, 60=N/A (default) -|228-229 | 2 |Status |status |e|See "Status Codes" below -|230-231 | 2 |Spare | |x|Not used -|============================================================================== - -OPEN-QUESTION: <> does not specify whether ETA time is UTC -or local. - -OPEN-QUESTION: No default is specified for the Status field. - -.Lock/Bridge/Terminal status codes -[frame="topbot",options="header"] -|============================================================================== -| 0 | Operational -| 1 | Limited operation -| 2 | Out of order -| 3 | N/A -|============================================================================== - -==== Number of persons on board (Inland AIS) ==== - -This message should be sent by inland vessels only, to inform about -the number of persons (passengers, crew, and shipboard personnel) on -board. - -A message 6 subtype. DAC = 200 FID = 55. Fixed length, 168 bits. - -//: Type 6(200/55) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit|u|0 = no retransmit (default), - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 200 -|82-87 | 6 |FID |fid |u|FID = 55 -|88-95 | 8 |# crew on board |crew |u|Unsigned integer - 0-254, - 255 = Unknown (default) -|96-108 | 13 |# passengers on board|passengers|u|Unsigned integer - 0-8190, - 8191 = Unknown (default) -|109-116 | 8 |# personnel on board |personnel |u|Unsigned integer - 0-254, - 255 = Unknown (default) -|117-167 | 51 |Spare | |x|Not used -|============================================================================== - -==== AtoN monitoring data (GLA) ==== - -This message provides AtoN (Aid to navigation) monitoring data for the General -Lighthouse Authorities (GLA), which consists of Trinity House (England & -Wales), Northern Lighthouse Board (Scotland) and the Commissioners of Irish -Lights (Ireland). It is described in <>. - -A message 6 subtype. DAC = 235 or 250 FID = 10. Fixed length: 136 bits. - -DAC and FI are user configurable, DAC=235/FI=10 is used in UK, DAC=250/FI=10 -in the Republic Of Ireland. - -The interval between the transmissions of these messages will be synchronized -with message 21, although not necessarily at the same reporting rate. If -Message 21 is not used at a particular site, then the reporting interval -should be selected to minimize the power requirement of the transponder, -whilst still providing enough data to enable meaningful diagnostic analysis. - -OPEN-QUESTION: <> lists a broadcast (type 8) variant of this -message, but without indicating how the Destination MMSI field is to -be set or interpreted. Robust implementations should accept and -process this variant. - -//: Type 6(235-250:10) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-70 | 1 |Retransmit flag |retransmit |u|0 = no retransmit (default), - 1 = retransmitted -|71-71 | 1 |Spare | |x|Not used -|72-81 | 10 |DAC |dac |u|DAC = 235 or 250 -|82-87 | 6 |FID |fid |u|FID = 10 -|88-97 | 10 |Analogue |ana_int |u|0.05-36V, 0.05V step - Supply voltage to AIS Unit - 0 = Not Used -|98-107 | 10 |Analogue (ext. #1)|ana_ext1 |u|0.05-36V, 0.05V step - 0 = Not Used -|108-117 | 10 |Analogue (ext. #2)|ana_ext2 |u|0.05-36V, 0.05V step - 0 = Not Used -|118-119 | 2 |RACON status |racon |u|00 = no RACON installed - 01 = RACON not monitored - 10 = RACON operational - 11 = RACON ERROR -|120-121 | 2 |Light status |light |u|00 = no light or no monitoring - 01 = Light ON - 10 = Light OFF - 11 = Light ERROR -|122 | 1 |Health |health |b|0 = Good Health, 1 = Alarm -|123-130 | 8 |Status (external) |stat_ext |u|7 Digital Input 0=Off, 1=On - : - : - 0 Digital Input 0=Off, 1=On -|131-131 | 1 |Position status |off_pos |b|0=On position, 1=Off position -|132-135 | 4 |Spare | |x|Not used -|============================================================================== - -=== Type 7: Binary Acknowledge === - -Message type 7 is a receipt acknowledgement to the senders of a -previous messages of type 6. Total length varies between 72 and 168 -bits by 32-bit increments, depending on the number of destination -MMSIs included. - -//: Type 7 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 7 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-69 | 30 |MMSI number 1 |mmsi1 |u|9 decimal digits -|70-71 | 2 |Sequence for MMSI 1 |mmsiseq1 |u|Not used -|72-101 | 30 |MMSI number 2 |mmsi2 |u|9 decimal digits -|102-103 | 2 |Sequence for MMSI 2 |mmsiseq2 |u|Not used -|104-133 | 30 |MMSI number 3 |mmsi3 |u|9 decimal digits -|134-135 | 2 |Sequence for MMSI 3 |mmsiseq3 |u|Not used -|136-165 | 30 |MMSI number 4 |mmsi4 |u|9 decimal digits -|166-167 | 2 |Sequence for MMSI 4 |mmsiseq4 |u|Not used -|============================================================================== - -Use of the MMSI sequence fields was introduced in ITU-1371-5 to -indicate the sequence number of the Type 6 to which this responds. -In earlier versions these were spare fields. - -=== Type 8: Binary Broadcast Message === - -Message type 8 is a broadcast message with unspecified binary payload. -The St. Lawrence Seaway AIS system, the USG PAWSS system, and the Port -Authority of London use this payload for local extension -messages. <> and <> describe payload use as -international extension messages. This type is variable in length up -to a maximum of 1008 bits (up to 5 AIVDM sentence payloads). - -//: Type 8 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |Designated Area Code |dac |u|Unsigned integer -|50-55 | 6 |Functional ID |fid |u|Unsigned integer -|56 |952 |Data |data |d|Binary data, - May be shorter than 952 bits. -|============================================================================== - -Interpretation of the binary payload is controlled by DAC/FID as in -message type 6. The following is a non-exhaustive list of standardized -DAC-FID pairs in use for type 8: - -[frame="topbot",options="header"] -|============================================================================== -| DAC |FID | Sub | Source | Status | Description -| 1 | 11 | | <> | Deprecated/In Use | Meteorological/Hydrological Data -| 1 | 13 | | <> | Deprecated | Fairway closed -| 1 | 15 | | <> | Deprecated | Extended ship and voyage -| 1 | 17 | | <> | In use | VTS-Generated/Synthetic targets -| 1 | 19 | | <> | Standard | Marine traffic signals -| 1 | 21 | | <> | Standard | Weather observation from ship -| 1 | 22 | | <> | In use | Area notice (broadcast) -| 1 | 24 | | <> | Standard | Extended ship and voyage -| 1 | 26 | | <> | Standard | Environmental -| 1 | 27 | | <> | Standard | Route info broadcast -| 1 | 29 | | <> | Standard | Text description broadcast -| 1 | 31 | | <> | In use | Meteorological and Hydrological -| 200 | 10 | | <> | Standard | Ship static and voyage related data -| 200 | 23 | | <> | Standard | EMMA warning report -| 200 | 24 | | <> | Standard | Water levels -| 200 | 40 | | <> | Standard | Signal status -| 316/366 | 1 | 2 | <> | In use | Wind -| 316/366 | 1 | 1 | <> | In use | Weather station -| 316/366 | 1 | 3 | <> | In use | Water level -| 316/366 | 1 | 6 | <> | In use | Water flow -| 316/366 | 2 | 1 | <> | In use | Lockage Order -| 316/366 | 2 | 2 | <> | In use | Estimated Lock Times -| 316/366 | 32 | 1 | <> | In use | Seaway Version Message -| 366 | 1 | 4 | <> | In use | PAWS Hydro / Current -| 366 | 1 | 6 | <> | In use | PAWS Hydro / Salinity Temp -| 366 | 1 | 3 | <> | In use | PAWS Vessel Procession Order -|============================================================================== - -DAC/FID pairs are assigned separately per message type. For St. Lawrence -Seaway messages, the DAC may be 316 (Canada) or 366 (U.S.) depending -on the transmitter location. - -Note that the apparent presence of one of these DAC/FID pairs does -not guarantee that the message is structured. Decoders should -perform range validation on the structured fields and interpret the -message as unstructured if any check fails. Actual false matches with -DAC/FID = 200/10 have been observed in the wild. - -DAC/FID pairs 1/23, 1/28, and 1/30 have addressed versions described -under type 6. - -FID types 11-15 are being phased out and are not to be used after 1 -Jan 2013. The deprecated IMO236 1/11 has a different binary layout from -the IMO289 1/31. FID type 17 is in use; there is a proposed -update for it in <>. - -Breakdowns of Message 8 subtypes from <> follow. - -==== Meteorological and Hydrological Data (IMO236) ==== - -A message 8 subtype. DAC = 001 FID = 11. Fixed length, 352 bits. -This is in use and described in <>, but has been deprecated by -<<289>> in favor of a message with the same title but FID = 31 and a -different binary layout. <> specifies a maximum interval between -broadcast of this message of 12 minutes. - -//: Type 8(1/11) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |u|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 11 -|56-79 | 24 |Latitude |lat |I3|Unit = minutes * 0.001, - 0x7FFFFF = N/A (default), - E positive, W negative. -|80-104 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, - 0xFFFFFF = N/A (default), - N positive, S negative. -|105-109 | 5 |Day (UTC) |day |u|1-31, 31=N/A (default) -|110-114 | 5 |Hour (UTC) |hour |u|0-23, 31=N/A (default) -|115-120 | 6 |Minute (UTC) |minute |u|0-59, 63=N/A (default) -|121-127 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed, knots, - 127 = N/A (default). -|128-134 | 7 |Gust Speed |wgust |u|10-min max wind speed, knots, - 127 = N/A (default). -|135-143 | 9 |Wind Direction |wdir |u|0-359, degrees from true north - 511 = N/A (default) -|144-152 | 9 |Wind Gust Direction|wgustdir |u|0-359, degrees fom true north - 511 = N/A (default) -|153-163 | 11 |Air Temperature |temperature |u|Dry bulb temp: 0.1 deg C - -60.0 to +60.0, - 2047 = N/A (default), -|164-170 | 7 |Relative Humidity |humidity |u|0-100%, units of 1%, - 127 = N/A (default). -|171-180 | 10 |Dew Point |dewpoint |u|-20.0 to +50.0: 0.1 deg C, - 1023 = N/A (default), -|181-189 | 9 |Air Pressure |pressure |u|800-1200hPa: units 1hPa, - 511 = N/A (default). -|190-191 | 2 |Pressure Tendency |pressuretend|e|0 = steady, - 1 = decreasing, - 2 = increasing, - 3 - N/A (default). -|192-199 | 8 |Horiz. Visibility |visibility |U1|0-25.0, units of 0.1nm - 255 = N/A (default) -|200-208 | 9 |Water Level |waterlevel |I1|-10.0 to +30.0 in 0.1m, - 511 = N/A (default). -|209-210 | 2 |Water Level Trend |leveltrend |e|0 = steady, - 1 = decreasing, - 2 = increasing, - 3 - N/A (default). -|211-218 | 8 |Surface Current Speed |cspeed |U1|0.0-25.0 knots: units 0.1 knot -|219-227 | 9 |Surface Current Direction |cdir |u|0-359: deg from true north, - 511 = N/A (default) -|228-235 | 8 |Current Speed #2 |cspeed2 |U1|0.0-25.0 in units of 0.1 knot, - 255 = N/A (default). -|236-244 | 9 |Current Direction #2 |cdir2 |u|0-359: deg. fom true north, - 511 = N/A (default) -|245-249 | 5 |Measurement Depth #2 |cdepth2 |U1|0-30m down: units 0.1m, - 31 = N/A (default). -|250-257 | 8 |Current Speed #3 |cspeed3 |U1|0.0-25.0: units of 0.1 knot, - 255 = N/A (default). -|258-266 | 9 |Current Direction #3 |cdir3 |u|0-359: degrees fom true north, - 511 = N/A (default). -|267-271 | 5 |Measurement Depth #3 |cdepth3 |U1|0-30m down: units 0.1m, - 31 = N/A (default). -|272-279 | 8 |Wave height |waveheight|U1|0-25m: units of 0.1m, - 255 = N/A (default). -|280-285 | 6 |Wave period |waveperiod|u|Seconds 0-60: - 63 = N/A (default). -|286-294 | 9 |Wave direction |wavedir |u|0-359: deg. fom true north, - 511 = N/A (default). -|295-302 | 8 |Swell height |swellheight|U1|0-25m: units of 0.1m - 255 = N/A (default). -|303-308 | 6 |Swell period |swellperiod|u|Seconds 0-60: - 63 = N/A (default). -|309-317 | 9 |Swell direction |swelldir |u|0-359: deg. fom true north, - 511 = N/A (default). -|318-321 | 4 |Sea state |seastate |e|See "Beaufort Scale" -|322-331 | 10 |Water Temperature |watertemp |U1|-10.0 to 50.0: units 0.1 C, - 1023 = N/A (default). -|332-334 | 3 |Precipitation |preciptype |e|See "Precipitation Types" -|335-343 | 9 |Salinity |salinity |U1|0.0-50.0%: units 0.1%, - 511 = N/A (default) -|344-345 | 2 |Ice |ice |e| 0 = No - 1 = Yes - 2 = (reserved for future use) - 3 = not available = default -|346-351 | 6 |Spare | |x|Not used -|============================================================================== - -<> says "If there is no data available, default value to be -transmitted is the highest available binary value for that particular -data field.", the above table reflects that. The day, hour and minute -have to be considered not available when all three are set to their -individual "N/A" value. For the latitude and the longitude, the -highest positive value is used, as the highest available binary value -for a signed integer is -1, which would forbid the -0.001/-0.001 -position. The replacement FID=31 message has different default values -that remove any ambiguities. - -<> gives the length of this message as 352, but lists only 336 -payload bits. - -Water level is deviation from local chart datum and includes tide. - -The waveheight field is labeled as "Significant" in <>, -for whatever that means. - -The seastate field has a note in <> reading "(manual input?)"? - -WMO 306 Code table 4.201 specifies the following precipitation type values: - -.Precipitation Types -[width="50%",frame="topbot",options="header"] -|=================================== -|Code |Precipitation Type -|0 |Reserved -|1 |Rain -|2 |Thunderstorm -|3 |Freezing rain -|4 |Mixed/ice -|5 |Snow -|6 |Reserved -|7 |N/A (default) -|=================================== - -.Beaufort Scale -[width="50%",frame="topbot",options="header"] -|=========================================================================== -|Scale|Description | Sea Conditions -|0 |Calm |Flat. -|1 |Light air |Ripples without crests. -|2 |Light breeze |Small wavelets. -| Crests of glassy appearance, not breaking. -|3 |Gentle breeze |Large wavelets. -| Crests begin to break; scattered whitecaps. -|4 |Moderate breeze|Small waves. -|5 |Fresh breeze |Moderate (1.2 m) longer waves. Some foam and spray. -|6 |Strong breeze |Large waves with foam crests and some spray. -|7 |High wind |Sea heaps up and foam begins to streak. -|8 |Gale |Moderately high waves with breaking crests -| forming spindrift. Streaks of foam. -|9 |Strong gale |High waves (6-7 m) with dense foam. -| Wave crests start to roll over. Considerable spray. -|10 |Storm |Very high waves. The sea surface is white and there -| is considerable tumbling. Visibility is reduced. -|11 |Violent storm |Exceptionally high waves. -|12 |Hurricane force|Huge waves. Air filled with foam and spray. Sea -| completely white with driving spray. Visibility -| greatly reduced. -|13 | |N/A (default) -|14-15| |Reserved -|=========================================================================== - -==== Fairway Closed ==== - -This message should be broadcast from shore stations to inform ships, -in particular to give guidance to large vessels about temporary closed -fairways or sections in ports. - -A message 8 subtype. DAC = 001 FID = 13. Fixed length, 472 bits. -Described in <> but deprecated by <>. - -//: Type 8(1/13) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 13 -|56-175 |120 |Reason For Closing |reason |t|20 6-bit characters -|176-295 |120 |Location Of Closing From|closefrom|t|20 6-bit characters -|296-415 |120 |Location of Closing To |closeto |t|20 6-bit characters -|416-425 | 10 |Radius extension |radius |u|0-1000, 10001 = N/A (default) -|426-427 | 2 |Unit of extension |extunit |u|0=m, 1=km, 2=nm, 3=cables -|428-432 | 5 |From day (UTC) |fday |u|1-31, 0=N/A (default) -|433-436 | 4 |From month (UTC) |fmonth |u|1-12, 0=N/A (default) -|437-441 | 5 |From hour (UTC) |fhour |u|0-23, 24=N/A (default) -|442-447 | 6 |From minute (UTC) |fminute |u|0-59, 60=N/A (default) -|448-452 | 5 |To day (UTC) |tday |u|1-31, 0=N/A (default) -|453-456 | 4 |To month (UTC) |tmonth |u|1-12, 0=N/A (default) -|457-461 | 5 |To hour (UTC) |thour |u|0-23, 24=N/A (default) -|462-467 | 6 |To minute (UTC) |tminute |u|0-59, 60=N/A (default) -|468-471 | 4 |Spare | |x|Not used -|============================================================================== - -No default is specified for the radius field in the standard. - -==== IMO236 Extended Ship Static and Voyage Related Data ==== - -This message should be used by a ship to report the height over keel. - -A message 8 subtype. DAC = 001 FID = 15 in <>. Fixed length, 72 bits. -Deprecated in <>. - -//: Type 8(1/15) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 15 -|55-66 | 11 |Air Draught |airdraught|u|Height in meters, - 0 = N/A (default), - 2047 = >= 2047 m, -|67-71 | 5 |Spare | |x|Not used -|============================================================================== - -==== VTS-Generated/Synthetic targets ==== - -A message 8 subtype. DAC = 001 FID = 17. Variable length: 176-536 -bits. This message is laid out identically in <> and -<>. In <> it is titled "Pseudo-AIS Targets". - -//: Type 8(1/17) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 17 -|56 | | |targets |a4|Synthetic targets array -|0-1 | 2 |Identifier type |idtype |e|0 = id is the MMSI number, - 1 = id is the IMO number, - 2 = id is the call sign, - 3 = Other (default). -|2-43 | 42 |Target identifier |id |u|Target ID data. -|44-47 | 4 |Spare | |x|Not used -|48-71 | 24 |Latitude |lat |I3|Minutes * 0.001, - 91000 = N/A (default), - N positive, S negative. -|72-96 | 25 |Longitude |lon |I3|Minutes * 0.001, - 181000 = N/A (default), - E positive, W negative. -|97-105 | 9 |Course Over Ground |course |u|0-359 deg from true north, - 360 = N/A (default). -|106-111 | 6 |Time Stamp |second |u|Second of UTC timestamp. -|112-121 | 10 |Speed Over Ground |speed |u|0-254 in knots, 255 = N/A. -|============================================================================== - -The interpretation of the target identifier field depends on the -preceding type key. For 0 and 1 it is a big-endian unsigned binary -integer (as shown above). For type 2 and 3 it is 6-bit ASCII text. An -unknown target is expressed by type 3 and the string "@@@@@@@". - -OPEN-QUESTION: <> says: "When MMSI or IMO number is used, the -least significant bit should equal bit zero of the Target Identifier." -It is unclear how "bit zero" is to be interpreted, but it is not -possible to reconcile interpreting it as the leading bit of the field -with AIS big-endian encoding. Settling this awaits live testing. - -The trailing eight fields may be repeated up to 3 times (for a total of 1 to 4 -field groups) to represent up to 4 targets. - -==== IMO289 Marine Traffic Signal ==== - -This message provides information on a signal station and status of -the control signal at the entrance of a harbour or channel where the -shipping direction controlled so that the traffic flow be kept in -order. - -A message 8 subtype described in <>. DAC = 001 FID = 19. Fixed -length: 360 bits. - -//: Type 8(1/19) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |u|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 19 -|56-65 | 10 |Message Linkage ID |linkage |u|Unsigned integer -|66-185 | 120 |Name of Signal Station|station |t|20 6-bit chars -|186-210 | 25 |Longitude |lon |I3|Unit = minutes * 0.001 - 181000 = N/A (default) - E positive, W negative. -|211-234 | 24 |Latitude |lat |I3|Unit = minutes * 0.001 - 91000 = N/A (default) - N positive, S negative. -|235-236 | 2 |Status of Signal |status |u|0=N/A (default - 1 = In regular service - 2 = Irregular service - 3 = Reserved for future use -|237-241 | 5 |Signal In Service |signal |e|See "Marine Traffic Signals" -|242-246 | 5 |UTC hour |hour |u|0-23, 24=N/A (default) -|247-252 | 6 |UTC minute |minute |u|0-59, 60=N/A (default) -|253-257 | 5 |Expected Next Signal |nextsignal|e|See "Marine Traffic Signals" -|258-359 | 102 |Spare | |x|Not used -|============================================================================== - -.Marine Traffic Signals -[width="50%",frame="topbot",options="header"] -|=========================================================================== -|Code |Position Fix Type -| 0 |N/A (default) -| 1 |IALA port traffic signal 1: Serious emergency – all vessels to stop -| or divert according to instructions. -| 2 |IALA port traffic signal 2: Vessels shall not proceed. -| 3 |IALA port traffic signal 3: Vessels may proceed. One way traffic. -| 4 |IALA port traffic signal 4: Vessels may proceed. Two way traffic. -| 5 |IALA port traffic signal 5: A vessel may proceed only when it has -| received specific orders to do so. -| 6 |IALA port traffic signal 2a: Vessels shall not proceed, except that -| vessels which navigate outside the main channel need not comply with -| the main message. -| 7 |IALA port traffic signal 5a: A vessel may proceed only when it has -| received specific orders to do so; except that vessels which navigate -| outside the main channel need not comply with the main message. -| 8 |Japan Traffic Signal - I = "in-bound" only acceptable. -| 9 |Japan Traffic Signal - O = "out-bound" only acceptable. -| 10 |Japan Traffic Signal - F = both "in- and out-bound" acceptable. -| 11 |Japan Traffic Signal - XI = Code will shift to "I" in due time. -| 12 |Japan Traffic Signal - XO = Code will shift to "O" in due time. -| 13 |Japan Traffic Signal - X = Vessels shall not proceed, except a vessel -| which receives the direction from the competent authority. -|14-31|Reserved -|=========================================================================== - -==== IMO289 Weather observation report from ship ==== - -There are two variants of this message. They are distinguished by bit 56, -the WMO bit. Field layouts after that bit vary depending on it. - -A message 8 subtype described in <>. DAC = 001 FID = 21. Fixed -length: 360 bits. - -//: Type 8(1/21) -.Weather observation report from ship: Non-WMO variant -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 21 -|56-56 | 1 |Variant |wmo |b|Constant: 0 in this variant -|57-176 | 120 |Location |location |t|20 6-bit characters -|177-201 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, - 181000 = N/A (default), - E positive, W negative. -|202-225 | 24 |Latitude |lat |I3|Unit = minutes * 0.001, - 91000 = N/A (default), - N positive, S negative. -|226-230 | 5 |UTC Day |day |u|1-31, 0=N/A (default) -|231-235 | 5 |UTC hour |hour |u|0-23, 24=N/A (default) -|236-241 | 6 |UTC minute |minute |u|0-59, 60=N/A (default) -|242-245 | 4 |Present Weather |weather |u|wmocode: 0-15 -|246-246 | 1 |Visibility Limit |vislimit |b|See below -|247-253 | 7 |Horiz. Visibility |visibility |U1|0.0-12.6nm, units = nm*0.1, - 127 = N/A (default). -|254-260 | 7 |Relative Humidity |humidity |u|0-100%: units of 1%, - 127 = N/A (default). -|261-267 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed knots, - 127 = N/A (default). -|268-276 | 9 |Wind Direction |wdir |u|0-359, deg. fom true north, - 360 = N/A (default). -|277-285 | 9 |Air Pressure |pressure |u|800-1200hPa: units 1hPa, - 402 = pressure >= 1201 hPa, - 403 - N/A (default), - else add 400 to value, -|286-289 | 4 |Pressure Tendency |pressuretend|u|WMO FM13 code -|290-300 | 11 |Air Temperature |airtemp |I1|Dry bulb temp: units 0.1C, - -60.0 to +60.0, - -1024 = N/A (default). -|301-310 | 10 |Water Temperature |watertemp |I1|-10.0 to 50.0 in 0.1 C, - 601 = N/A (default), - else -10C after scaling. -|311-316 | 6 |Wave period |waveperiod |u|Seconds: 0-60, - 63 = N/A (default). -|317-324 | 8 |Wave height |waveheight |U1|0-25m in units of 0.1m, - 255 = N/A (default). -|325-333 | 9 |Wave direction |wavedir |u|0-359: deg. fom true north, - 360 = N/A (default). -|334-341 | 8 |Swell height |swellheight |U1|0-25m: units 0.1m, - 255 = N/A (default) -|342-350 | 9 |Swell direction |swelldir |u|0-359: deg, fom true north, - 360 = N/A (default). -|351-356 | 6 |Swell period |swellperiod |u|Seconds: 0-60, - 63 = N/A (default). -|357-359 | 3 |Spare | |x|Not used -|============================================================================== - -The vislimit bit, when on, indicates that the maximum range of the -visibility equipment was reached and the visibility reading shall be -regarded as > x.x NM. - -The standard (<>) does not list the WMO FM13 codes. -The following table applies: - -.Weather observation report from ship: WMO Code 45501 -[width="50%",frame="topbot",options="header"] -|=========================================================================== -|Code |Precipitation Type -| 0 |Clear (no clouds at any level) -| 1 |Cloudy -| 2 |Rain -| 3 |Fog -| 4 |Snow -| 5 |Typhoon/hurricane -| 6 |Monsoon -| 7 |Thunderstorm -| 8 |N/A (default) -| 9-15|Reserved for future use -|=========================================================================== - -.Weather observation report from ship: WMO variant -[frame="topbot",options="header"] -|============================================================================== -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 21 -|56-56 | 1 |Variant |wmo |u|Constant: 1 in this variant -|57-72 | 16 |Longitude |lon |I3|Unsigned: minutes * 0.01, - E positive, W negative, - Lon = (value / 100) – 180, - 65536 = N/A (default). -|73-87 | 15 |Latitude |lat |I3|Unsigned: minutes * 0.01, - N positive, S negative, - Lat = (value / 100) – 90, - 32767 = N/A (default). -|88-91 | 4 |UTC Month |month |u|1-12, 15=N/A (default) -|92-97 | 6 |UTC Day |day |u|1-31, 63=N/A (default) -|98-102 | 5 |UTC hour |hour |u|0-23, 31=N/A (default) -|103-105 | 3 |UTC minute |minute |u|0-50, 7=N/A (default), - Minute = (value * 10). -|106-112 | 7 |Course Over Ground |course |u|0-359, unit = 1 degree, - average over last 10 minutes. -|113-117 | 5 |Speed Over Ground |speed |U1|0-14.5m/s: - SOG = (value * 0.5) for 0-29, - 30 = 15 m/s and more, - average over last 10 minutes. - 31 = N/A (default) -|118-124 | 7 |Heading of the ship |heading |u|5-360: units of 5 degrees, - HDT = (value * 5) for 1-72, - average over last 10 minutes. - 127 = N/A (default) -|125-135 | 11 |Pressure at sea level |pressure|U1|90-1100 hPa: - P = (value/10)+900 for 0-2000 -|136-145 | 10 |Pressure Change |pdelta |U1|-50-+50hPa: units of 0.1hPa, - d = (value/10)-50 for 0-100, - averaged over last 3 hours. - 1023 = N/A (default) -|146-149 | 4 |Pressure Tendency |ptend |u|WMO BUFR table 010063: - Averaged over last 3 hours, - 0-8, 15 = N/A. -|150-156 | 7 |True Wind Direction |twinddir|u|005-360: deg: - average over last 10 minutes, - dir = (value*5), value 1-72, - 0 = calm, - 127 = N/A (default). -|157-164 | 8 |True Wind Speed |twindspeed|u|0-127 m/s: - average over last 10 mins, - speed = value * 0.5, - 255 = N/A (default). -|165-171 | 7 |Relative Wind Direction|rwinddir |u|005-360 deg: - average over last 10 mins, - dir = (value*5) for 1-72, - 0 = calm, - 127 = N/A (default). -|172-179 | 8 |Relative Wind Speed |rwindspeed|U1|0-127 m/s: - average over last 10 mins, - speed = val*0.5 for 0-254, - 255 = N/A (default). -|180-187 | 8 |Maximum Gust Speed |mgustspeed|U1|0-127 m/s: - speed = val*0.5 for 0-254, - 255 = N/A (default), -|188-194 | 7 |Maximum Gust Direction |mgustdir |u|05-360 deg: - dir = (value*5) for 1-72, - 0 = calm, - 127 = N/A (default). -|195-204 | 10 |Air Temperature |airtemp |U1|Dry bulb temp: units 0.1C, - 223-323K (c.-50C - +50C). - T = (val/10)+223 for 0-1000, - 1023 = N/A (default). -|205-211 | 7 |Relative Humidity |humidity |u|0-100%: units of 1%, - 127 = N/A (default). -|212-220 | 9 |Sea Surface Temperature|surftemp |U1|268-318K (c.-5C - +45C): - T = (val/10)+268 for 0-500, - 511 = N/A (default). -|221-226 | 6 |Horiz. Visibility |visibility|U2|0-50000m, - Vis = (val**2)*13.073 for 0-62, - 63 = N/A (default). -|227-235 | 9 |Present Weather |weather |u|BUFR table 020003: - Codes 0-510, - 511 = N/A (default). -|236-240 | 5 |Past Weather 1 |pweather1 |u|BUFR table 020005: - Codes 0-30, - 31 = N/A (default). -|241-245 | 5 |Past Weather 2 |pweather2 |u|BUFR table 020004: - Codes 0-30, - 31 = N/A (default). -|246-249 | 4 |Total Cloud Cover |totalcloud|u|0-100%: - Cover = val * 10% for 0-10, - 15 = N/A (default.) -|250-253 | 4 |Cloud amount (low) |lowclouda |u|0-14: BUFR table 020011: - 15 = N/A (default). -|254-259 | 6 |Cloud type (low) |lowcloudt |u|0-62: BUFR table 020012: - 63 = N/A (default). -|260-265 | 6 |Cloud type (middle) |midcloudt |u|0-62: BUFR table 020012: - 63 = N/A (default). -|266-271 | 6 |Cloud type (high) |highcloudt|u|0-62: BUFR table 020012: - 63 = N/A (default). -|272-278 | 7 |Height of cloud base |cloudbase |U2|0-2500m: - h = (value**2)*.0.16 for 0-125, - 126 = more than 2500m, - 127 = N/A (default). -|279-283 | 5 |Period of Wind Waves |wwperiod |u|0-30s: - 31 = N/A (default). -|284-289 | 6 |Height of Wind Waves |wwheight |u|Height in meters: 0-30, - h = (value * 0.5) for 0-60, - 63 = N/A (default). -|290-295 | 6 |First Swell Direction |swelldir1 |u|10-360 deg: - dir = (value*10) for 1-36, - 0 = calm, - 63 = N/A (default). -|296-300 | 5 |First Swell Period |swperiod1 |u|Period in seconds: 0-30, - 31 = N/A (default). -|301-306 | 6 |First Swell Height |swheight1 |U1|Height in meters: 0-30, - h = (value * 0.5) for 0-60, - 63 = N/A (default). -|307-312 | 6 |Second Swell Direction |swelldir2 |u|10-360 deg: - dir = (value*10) for 1-36, - 0 = calm, - 63 = N/A (default). -|313-317 | 5 |Second Swell Period |swperiod2 |u|Period in seconds: 0-30, - 31 = N/A (default). -|318-323 | 6 |Second Swell Height |swheight2 |U1|Height in meters: 0-30, - h = (value * 0.5) for 0-60, - 63 = N/A (default). -|324-330 | 7 |Ice deposit (thickness)|icedeposit|u|Thickness: 0-126cm, - 127 = N/A (default). -|331-333 | 3 |Rate of Ice Accretion |icerate |u|0-6: BUFR table 020032: - 7 = N/A (default). -|334-336 | 3 |Cause of Ice Accretion |icecause |u|0-6: BUFR table 020033: - 7 = N/A (default). -|337-341 | 5 |Sea Ice Concentration |seaice |u|0-30: BUFR table 020034: - 31 = N/A (default). -|342-345 | 4 |Amount and Type of Ice |icetype |u|0-14: BUFR table 020035: - 15 = N/A (default). -|346-350 | 5 |Ice Situation |icestate |u|0-30: BUFR table 020036: - 31 = N/A (default). -|351-355 | 5 |Ice Development |icedevel |u|0-30: BUFR table 020037: - 31 = N/A (default). -|356-359 | 4 |Bearing of Ice Edge |icebearing|u|Bearing: 45-360 deg, - dir = (value*45) for 1-8, - 15 = N/A (default). -|============================================================================== - -The "minute" entry actually only identifies the end of a 10-minute interval. - -In <>, the Latitude formula is given as "Lat = (value / 100) – 9000". -This is incorrect; the decrement needs to be 90 for the range to be -90..+90. - -Swell directions are arrival directions. - -==== IMO289 Area Notice (broadcast) ==== - -This should be used to broadcast time- and location-dependent information about -hazards to navigation. For information-lifetime restrictions and usage -guidance, refer to <>. - -A message 8 subtype. DAC = 001 FID = 22. 196 to 981 bits. There is a -related Message 6 subtype for addressed use. - -The message consists of a fixed-length header of 111 bits, followed by 1 to -10 sub-area indications which are fixed-length records 87 bits long. Here -is the message header format: - -//: Type 8(1/22) -.Area Notice (addressed) message header -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 22 -|56-65 | 10 |Message Linkage ID |linkage |u|Unsigned integer -|66-72 | 7 |Notice Description |notice |u|See table below -|73-76 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) -|77-81 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|82-86 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|87-92 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|93-110 | 18 |Duration |duration |In minutes, - 262143 = N/A (default), - 0 = cancel this notice. -|143 | | |subarea |a10|Subarea array -|0-2 | 2 | |shape |u|Subarea shape -|3-86 | 85 |Subarea Payload |payload |d|Subarea payload -|============================================================================== - -The sub-area indications are as described under the addressed form, -message type 6 with DAC = 1 and FID = 23. - -==== IMO289 Extended Ship Static and Voyage Related Data ==== - -This message should be used by a ship to report the height over keel. - -A message 8 subtype. DAC = 001 FID = 24 in <>. Fixed length, 360 bits. -Replaces a deprecated trial message from <>. - -//: Type 8(1/24) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in CNB -|8-37 | 30 |Source MMSI |mmsi |u|9 digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 24 -|56-65 | 10 |Message Linkage ID |linkage |u|Unsigned integer -|66-78 | 13 |Air Draught |airdraught |u|Unsigned int, in 0.1m - 1-81.9 m. - 0 = N/A (default) - 81.91 = >= 81.91 m -|79-108 | 30 |Last Port Of Call |lastport |t|5 6-bit chars, UN locode -|109-138 | 30 |Next Port Of Call |nextport |t|5 6-bit chars, UN locode -|139-168 | 30 |Second Port Of Call |secondport |t|5 6-bit chars, UN locode -|169-170 | 2 |AIS Class A |ais_state |e|See "SOLAS Status" -|171-172 | 2 |Automatic Tracking Aid |ata_state |e|See "SOLAS Status" -|173-174 | 2 |BNWAS |bnwas_state |e|See "SOLAS Status" -|175-176 | 2 |ECDIS Back-up |ecdisb_state |e|See "SOLAS Status" -|177-178 | 2 |Paper Nautical Chart |chart_state |e|See "SOLAS Status" -|179-180 | 2 |Echo sounder |sounder_state |e|See "SOLAS Status" -|181-182 | 2 |Electronic plotting aid|epaid_state |e|See "SOLAS Status" -|183-184 | 2 |Emergency steering gear|steer_state |e|See "SOLAS Status" -|185-186 | 2 |GNSS |gnss_state |e|See "SOLAS Status" -|187-188 | 2 |Gyro compass |gyro_state |e|See "SOLAS Status" -|189-190 | 2 |LRIT |lrit_state |e|See "SOLAS Status" -|191-192 | 2 |Magnetic compass |magcomp_state |e|See "SOLAS Status" -|193-194 | 2 |NAVTEX |navtex_state |e|See "SOLAS Status" -|195-196 | 2 |Radar (ARPA) |arpa_state |e|See "SOLAS Status" -|197-198 | 2 |Radar (S-band) |sband_state |e|See "SOLAS Status" -|199-200 | 2 |Radar (X-band) |xband_state |e|See "SOLAS Status" -|201-202 | 2 |Radio HF |hfradio_state |e|See "SOLAS Status" -|203-204 | 2 |Radio INMARSAT |inmarsat_state|e|See "SOLAS Status" -|205-206 | 2 |Radio MF |mfradio_state |e|See "SOLAS Status" -|207-208 | 2 |Radio VHF |vhfradio_state|e|See "SOLAS Status" -|209-210 | 2 |Speed Log over ground |grndlog_state |e|See "SOLAS Status" -|211-212 | 2 |Speed Log through water|waterlog_state|e|See "SOLAS Status" -|213-214 | 2 |THD |thd_state |e|See "SOLAS Status" -|215-216 | 2 |Track control system |tcs_state |e|See "SOLAS Status" -|217-218 | 2 |VDR/S-VDR |vdr_state |e|See "SOLAS Status" -|219-220 | 2 |Reserved | |x|Not used -|221-224 | 4 |Ice Class |iceclass |e|See "Ice Class" -|225-242 | 18 |Shaft Horsepower |horsepower |u|Total ship HP: 1hp units, - 262,142 = >= 262,142hp, - 262,143 = N/A (default). -|243-254 | 12 |VHF Working Channel |vhfchan |u|Channel number, - 0 = N/A (default). -|255-296 | 42 |Lloyd's Ship Type |lshiptype |t|7 six-bit characters -|297-314 | 18 |Gross Tonnage |tonnage |u|0-262,141, - 262,142 = >= 262,142hp, - 262,143 = N/A (default). -|315-316 | 2 |Laden or Ballast |lading |e|0 = N/A (default), - 1 = Laden, - 2 = Ballast, - 3 = Not in use. -|317-318 | 2 |Heavy Fuel Oil Bunkered|heavyoil |e|0 = N/A (default), - 1 = No, - 2 = Yes, - 3 = Not in use. -|319-320 | 2 |Light Fuel Oil Bunkered|lightoil |e|0 = N/A (default), - 1 = No, - 2 = Yes, - 3 = Not in use. -|321-322 | 2 |Diesel Oil Bunkered |dieseloil |e|0 = N/A (default), - 1 = No, - 2 = Yes, - 3 = Not in use. -|323-336 | 14 |Total Bunker Oil |totaloil |u|0-16381 in tonnes, - 16382 = >= 16382 tonnes, - 16382 = N/A (default). -|337-349 | 13 |Number of persons |persons |u|0 = N/A (default), - 1-8190, - 8191 = >= 8191. -|350-359 | 10 |Spare | |x|Not used -|============================================================================== - -The special value of 81.91 for air draught is probably a drafting -error in <>, as the scaled field does not have the precision -required to represent it. The actual special value is unknown. - -The 2-bit _state fields describe the operational state of various sorts of -SOLAS-required navigational equipment. GNSS systems may include GPS, Loran-C, or GLONASS. BNWAS is the Bridge Navigational Watch Alarm System. THD is a -Transmitting Heading Device. Paper Nautical Chart state is officially -"ECDIS/Paper Nautical Chart" state in <>. Status codes should be -interpreted according to the following table: - -.SOLAS Status -[width="50%",frame="topbot",options="header"] -|============================================================================= -|Code |Meaning -|0 |Not available or requested (default) -|1 |Equipment operational -|2 |Equipment not operational -|3 |No data (equipment may or may not be on board/or its status is unknown) -|============================================================================= - -.Ice Class -[width="50%",frame="topbot",options="header"] -|============================================================================= -|Code |Meaning -|0 |Not classified -|1 |IACS PC 1 -|2 |IACS PC 2 -|3 |IACS PC 3 -|4 |IACS PC 4 -|5 |IACS PC 5 -|6 |IACS PC 6 / FSICR IA Super / RS Arc5 -|7 |IACS PC 7 / FSICR IA / RS Arc4 -|8 |FSICR IB / RS Ice3 -|9 |FSICR IC / RS Ice2 -|10 |RS Ice1 -|11-14|Reserved for future use -|15 |Not available = default -|============================================================================= - -ACS = International Association of Classification Societies - -PC = Polar Class. For further details, see IACS Req. 2007 Requirements -concerning POLAR CLASS and MSC/Circ.1056 and MEPC/Circ.399 on -Guidelines for ships operating in Arctic ice-covered waters. - -FSICR = Finnish-Swedish Ice Class Rules. For further details, see -Finnish Maritime Administration's Bulletin No.10/10.12.2008 Ice class -regulations 2008 (Finnish-Swedish ice class rules). Note: Authorized -classification society equivalents for the Finnish-Swedish Ice Class -Rules should also be recognized, as issued in the Finnish Maritime -Administration's Bulletin No.4/2.4.2007 (as amended). Both bulletins -can be found at www.fma.fi. - -RS = Russian Maritime Register of Shipping. For further details see -Rules for the classification and construction of seagoing ships, -Edition 2008. - -VHF channel number is encoded according to Recommendation ITU-R M.1084. - -The lshiptype field uses Lloyd's Register STATCODE 5 encoding. - -==== IMO289 Environmental ==== - -A message 8 subtype. DAC = 001 FID = 26. Variable length: 168-1008 bits. - -//: Type 8(1/26) -.Environmental message header -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 26 -|56 | | |reports |a5|Sensor records array -|0-3 | 4 |Sensor Report Type |sensor |u|See table below -|4-8 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|9-13 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|14-19 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|20-26 | 7 |Site ID |site |u|Binary ID of sensor site -|27-111 | 85 |Sensor payload |payload |d|Sensor payload data -|============================================================================== - -The fixed header is followed by 1-5 sensor records, each 112 bits -long. The Sensor Report Type is interpreted as follows, and controls -the interpretation of the sensor payload data. - -.Sensor report types -[frame="topbot",options="header"] -|============================================================================== -| 0 | Site location -| 1 | Station ID -| 2 | Wind -| 3 | Water level -| 4 | Current flow (2D) -| 5 | Current flow (3D) -| 6 | Horizontal current flow -| 7 | Sea state -| 8 | Salinity -| 9 | Weather -| 10| Air gap/Air draft -| 11| (reserved for future use) -|============================================================================== - -Here are the payload types for each variant: - -.Site location payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-27 | 28 |Longitude |lon |I4|As in Common Navigation Block -|28-54 | 27 |Latitude |lat |I4|As in Common Navigation Block -|55-65 | 11 |Altitude |alt |u|Sensor altitude above MSL, - 0-200 in units of 0.1m, - 2001 = 200.1 m or higher, - 2002 = N/A (default), - 2003-2046 reserved. -|66-69 | 4 |Sensor owner |owner |e|See "Sensor Owner Codes" -|70-72 | 3 |Data timeout |timeout |e|See "Data Timeout Codes" -|73-84 | 12 |Spare | |x|Not used -|============================================================================== - -.Sensor Owner Codes -[frame="topbot",options="header"] -|============================================================================== -| 0 | Unknown (default) -| 1 | Hydrographic office -| 2 | Inland waterway authority -| 3 | Coastal directorate -| 4 | Meteorological service -| 5 | Port Authority -| 6 | Coast guard -| 7-13 | (reserved for future use) -| 14 | (reserved for regional use) -|============================================================================== - -.Data Timeout Codes -[frame="topbot",options="header"] -|============================================================================== -| 0 | No time period (default) -| 1 | 10 minutes -| 2 | 1 hour -| 3 | 6 hours -| 4 | 12 hours -| 5 | 24 hours -| 6-7 | (reserved for future use) -|============================================================================== - -.Station ID payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -| 0 | 84 |Name |name |t|14 chars of six-bit ASCII. -| 84 | 1 |Spare | |x|Not used -|============================================================================== - -.Wind report payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-6 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed, - 0-120 in 1-knot units, - 121 = 121 knots or greater, - 122 = N/A (default), - 123-126 = reserved. -|7-13 | 7 |Wind Gust |wgust |u|10-min max wind speed, - 0-120 in 1-knot units, - 121 = 121 knots or greater, - 122 = N/A (default), - 123-126 = reserved. -|14-22 | 9 |Wind Direction |wdir |u|0-359, degrees fom true north - >=360 = N/A (default) -|23-31 | 9 |Wind Gust Direction|wgustdir |u|0-359, degrees fom true north - >=360 = N/A (default) -|32-34 | 3 |Sensor Description |sensortype |e|See "Sensor Types" -|35-41 | 7 |Forecast Wind Speed|fwspeed |u|Predicted average wind speed, - 0-120 in 1-knot units, - 121 = 121 knots or greater, - 122 = N/A (default), - 123-126 = reserved. -|42-48 | 7 |Forecast Wind Gust |fwgust |u|Predicted max wind speed, - 0-120 in 1-knot units, - 121 = 121 knots or greater, - 122 = N/A (default), - 123-126 = reserved. -|49-57 | 9 |Forecast Wind Direction|fwdir |u|0-359, degrees fom true north - >=360 = N/A (default) -|58-62 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|63-67 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|68-73 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|74-81 | 8 |Duration |duration |u|Forecast duration in minutes, - 255 = N/A (default), - 0 = cancel forecast. -|82-84 | 3 |Spare | |x|Not used -|============================================================================== - -The timestamp group is intended as a valid time of forecast. - -.Sensor Types -[frame="topbot",options="header"] -|============================================================================== -| 0 | No data (default) -| 1 | Raw real time -| 2 | Real time with quality control -| 3 | Predicted (based on historical statistics) -| 4 | Forecast (predicted, refined with real-time information) -| 5 | Nowcast (a continuous forecast) -| 6 | (reserved for future use) -| 7 | Sensor not available -|============================================================================== - -.Water level report payload -[frame="topbot",options="header"] -|============================================================================== -|0-0 | 1 |Water Level Type |absolute |b|False if relative to - reference datum. -|1-16 | 16 |Water Level |level |i|In 0.001 meter steps, - -327.67 to 327.67, - -32767 = -327.67m or less, - 32767 = 327.67m or more, - -32768 = N/A (default). -|17-18 | 2 |Water Level Trend |leveltrend |u| 0 = increasing, - 1 = decreasing, - 2 = steady, - 3 = N/A (default). -|19-23 | 5 |Vertical Reference Datum |datum |u|See table below -|24-26 | 3 |Sensor Description |sensortype |e|See "Sensor Types" -|27-27 | 1 |Forecast Water Level Type|absolute |b|False if relative to - reference datum. -|28-43 | 16 |Forecast Water Level |level |i|In 0.001 meter steps, - -327.67 to 327.67, - -32767 = -327.67m or less, - 32767 = 327.67m or more, - -32768 = N/A (default). -|44-48 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|49-53 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|54-59 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|60-67 | 8 |Duration |duration |u|Forecast duration in minutes, - 255 = N/A (default), - 0 = cancel forecast. -|68-84 | 17 |Spare | |x|Not used -|============================================================================== - -IMO289 says water level is in 0.1m steps, but this is incompatible with the -two digits of precision in the range. - -The timestamp group is intended as a valid time of forecast. - -.Vertical Reference Datum -[frame="topbot",options="header"] -|============================================================================== -| 0 | Mean Lower Low Water (MLLW) -| 1 | International Great Lakes Datum (IGLD-85) -| 2 | Local river datum -| 3 | Station Datum (STND) -| 4 | Mean Higher High Water (MHHW) -| 5 | Mean High Water (MHW) -| 6 | Mean Sea Level (MSL) -| 7 | Mean Low Water (MLW) -| 8 | National Geodetic Vertical Datum (NGVD-29) -| 9 | North American Vertical Datum (NAVD-88) -| 10 | World Geodetic System (WGS-84) -| 11 | Lowest Astronomical Tide (LAT) -| 12 | pool -| 13 | gauge -| 14 | Unknown/not available (default) -| 15-30| Reserved for future use -|============================================================================== - -.Current flow (2D) report payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-7 | 8 |Current Speed #1 |cspeed1 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|8-16 | 9 |Current Direction #1 |cdir1 |u|0-359: deg from true north, - >=360 = N/A (default). -|17-25 | 9 |Measurement Depth #1 |cdepth1 |u|0-360m down: units 1m, - 361 = 361m or greater, - 362 = N/A (default), - 363-511 (reserved). -|26-33 | 8 |Current Speed #2 |cspeed2 |U1|0.0-24.5 knots, - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|34-42 | 9 |Current Direction #2 |cdir2 |u|0-359: deg. fom true north, - >=360 = N/A (default) -|43-51 | 9 |Measurement Depth #2 |cdepth2 |u|0-360m down: units 1m, - 361 = 361m or greater, - 362 = N/A (default), - 363-511 (reserved). -|52-59 | 8 |Current Speed #3 |cspeed3 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|60-68 | 9 |Current Direction #3 |cdir3 |u|0-359: degrees fom true north, - >=360 = N/A (default). -|69-77 | 9 |Measurement Depth #3 |cdepth3 |u|0-360m down: units 1m, - 361 = 361m or greater, - 362 = N/A (default), - 363-511 (reserved). -|78-80 | 3 |Sensor Description |sensortype|e|See "Sensor Types" -|81-84 | 4 |Spare | |x|Not used -|============================================================================== - -.Current flow (3D) payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-7 | 8 |Current Vector component North (u) #1|cnorth1 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|8-15 | 8 |Current Vector component East (v) #1|ceast1 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|16-23 | 8 |Current Vector component Up (z) #1 |cup1 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|24-32 | 9 |Measurement Depth #1 |cdepth1 |u|0-360m down: - units 1m, - 361 = 361m or greater, - 362 = N/A (default), - 363-511 (reserved). -|33-40 | 8 |Current Vector component North (u) #2|cnorth2 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|41-48 | 8 |Current Vector component East (v) #2|ceast2 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|49-56 | 8 |Current Vector component Up (z) #2 |cup2 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|57-65 | 9 |Measurement Depth #2 |cdepth2 |u|0-360m down: - units 1m, - 361 = 361m or greater, - 362 = N/A (default), - 363-511 (reserved). -|66-68 | 3 |Sensor Description |sensortype|e|See "Sensor Types" -|69-84 | 16 |Spare | |x|Not used -|============================================================================== - -.Horizontal current report payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-8 | 9 |Current Bearing #1 |bearing1 |u|0-359: deg from true north, - >=360 = N/A (default). -|9-15 | 7 |Current Distance #1 |distance1 |u|0-120m: - 121 = 121m or greater, - 122 = N/A (default), - 123-127 (reserved). -|16-23 | 8 |Current Speed #1 |speed1 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|24-32 | 9 |Current Direction #1 |direction1|u|0-359: deg from true north, - >=360 = N/A (default). -|33-41 | 9 |Measurement Depth #1 |depth1 |u|0-360m down: units 1m, - 361 = 361m or greater, - 362 = N/A (default), - 363-511 (reserved). -|42-50 | 9 |Current Bearing #2 |bearing1 |u|0-359: deg from true north, - >=360 = N/A (default). -|51-57 | 7 |Current Distance #2 |distance1 |u|0-120m: - 121 = 121m or greater, - 122 = N/A (default), - 123-127 (reserved). -|58-65 | 8 |Current Speed #2 |speed1 |U1|0.0-24.5 knots: - units 0.1 knots, - 246 = speed >= 24.6 knots, - 247 = N/A (default), - 248-255 (reserved). -|66-74 | 9 |Current Direction #2 |direction1|u|0-359: deg from true north, - >=360 = N/A (default). -|75-83 | 9 |Measurement Depth #2 |depth1 |u|0-360m down: units 1m, - 361 = 361m or greater, - 362 = N/A (default), - 363-511 (reserved). -|84-84 | 1 |Spare | |x|Not used -|============================================================================== - -.Sea state report payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-7 | 8 |Swell Height |swheight |U1|Units 0.1m: 0.0-24.5m, - 246 = height >= 24,6m, - 247 = N/A (default), - 248-255 reserved, - else h = (value * 0.5). -|8-13 | 6 |Swell Period |swperiod |u|Period in seconds: - 0-60, - 61 = N/A (default), - 62-63 (reserved). -|14-22 | 9 |Swell Direction |swelldir |u|0-359 deg: - 0-359 true bearing, - 360 = N/A (default), - 361-511 reserved, -|23-26 | 4 |Sea State |seastate |u|Beaufort scale: 0-12 - >= 13 = N/A (default) -|27-29 | 3 |Swell Sensor Description |swelltype |e|See "Sensor Types" -|30-39 | 10 |Water Temperature |watertemp |U1|-10.0 to 50.0: - units 0.1 C, - >=601 = N/A (default). - 602-1023 reserved, - else -10.0m after scaling. -|40-46 | 7 |Water Temperature Depth |distance1 |U1|0.0-12.0m: 0.1m units, - 121 = 12.1m or greater, - 122 = N/A (default), - 123-126 (reserved). -|47-49 | 3 |Depth Sensor Description |depthtype |e|See "Sensor Types" - -|50-57 | 8 |Wave Height |waveheight|U1|Height 0.0-24.5m: - units 0.1m, - 246 = height >= 24.6m, - 247 N/A (default), - 248-255 reserved. -|58-63 | 6 |Wave Period |waveperiod|u|0-60: units of seconds, - 61 = N/A (default), - 62-63 reserved. -|64-72 | 9 |Wave Direction |wavedir |u|0-359: true bearing, - 360 = N/A (default), - 361-511 reserved. -|73-75 | 3 |Wave Sensor Description |wavetype |e|See "Sensor Types" -|76-84 | 9 |Salinity |salinity |U1|0.0-50.0%: - units of 0.1% - 501 = salinity >= 50.1% - 502 = data N/A (default) - 503 - sensor N/A, - 504-511 reserved. -|============================================================================== - -The standard does not fix the meaning of a water temperature depth of 127. - -.Salinity report payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-9 | 10 |Water Temperature |watertemp |U1|-10.0 to 50.0: - units 0.1 C, - >=601 = N/A (default). - 602-1023 reserved, - else -10.0m after scaling. -|10-19 | 10 |Conductivity |conductivity |U1|In Siemens/m, 0.0-7.0, - 0.1 S/m steps, - 701 = not less than 7.01, - 702 = data N/A, - 703 = sensor N/A (default), - 704-1023 (reserved). -|20-35 | 16 |Water Pressure |pressure |U1|Water pressure: 0.0-6000.0, - 0.1 decibar steps, - 60001 = pressure >= 6000.1, - 60002 = data N/A, - 60003 = sensor N/A (default), - 60004-65536 reserved. -|36-44 | 9 |Salinity |salinity |U1|0.0-50.0%: - units of 0.1% - 501 = salinity >= 50.1% - 502 = data N/A (default) - 503 - sensor N/A, - 504-511 reserved. -|45-46 | 2 |Salinity Type |salinitytype|e|0 = measured, - 1 = calculated using PSS-78, - 2 = calculated using other method, - 3 = reserved. -|47-49 | 3 |Sensor Description |sensortype |e|See "Sensor Types" -|50-84 | 35 |Spare | |x|Not used -|============================================================================== - -No default is specified for salinity type. - -.Weather report payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-10 | 11 |Air Temperature |temperature|i|Dry bulb temp: 0.1 deg C - -60.0 to +60.0, - -1024 = data N/A (default), - 601-1023 reserved. -|11-13 | 3 |Temp. Sensor Type |sensortype |e|See "Sensor Types" -|14-15 | 2 |Precipitation Type |preciptype |e|0 = rain, - 1 = rain and snow, - 2 = rain and snow, - 3 = other. -|16-23 | 8 |Horiz. Visibility |visibility |U1|Units of 0.1 nautical miles, - 0.0-24.0, - 241 = visibility >= 24.1nm, - 242 = data N/A, - 243 = sensor N/A (default), - 244-255 reserved. -|24-33 | 10 |Dew Point |dewpoint |i|-20.0 to +50.0: 0.1 deg C, - 501 = N/A (default), - 502-511 reserved, - -511--201 reserved. -|34-36 | 3 |Dewpoint Sensor Type|dewtype |e|See "Sensor Types". - - - -|37-45 | 9 |Air Pressure |pressure |u|0 = pressure <= 800hpA, - 1-401 = 800-1200hPa, - 402 = pressure >= 1201 hPa, - 403 - data N/A (default), - 404-511 reserved. -|46-47 | 2 |Pressure Tendency |pressuretend |e|0 = steady, - 1 = decreasing, - 2 = increasing, - 3 - N/A (default). -|48-50 | 3 |Pressure Sensor Type|pressuretype|e|See "Sensor Types" -|51-59 | 9 |Salinity |salinity |U1|0.0-50.0%: - units of 0.1% - 501 = salinity >= 50.1% - 502 = data N/A (default) - 503 - sensor N/A, - 504-511 reserved. -|60-84 | 25 |Spare | |x|Not used -|============================================================================== - -The standard does not specify how to code 'Precipitation Type' when -there is none. - -.Air Gap/Air Draft report payload -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-12 | 13 |Air Draught |airdraught |U1|1-81.9m in 0.1m steps, - 8191 = distance >= 81.91m, - 0 = N/A (default). -|13-25 | 13 |Air Gap |airgap |U1|1-81.9m in 0.1m steps, - 8191 = distance >= 81.91m, - 0 = N/A (default). -|26-27 | 2 |Air Gap Trend |gaptrend |e|0 = steady, - 1 = rising, - 2 = falling, - 3 = N/A (default). -|28-40 | 13 |Forecast Air Gap |fairgap |U1|1-81.9m in 0.1m steps, - 8191 = distance >= 81.91m, - 0 = N/A (default). -|41-45 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) -|46-50 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) -|51-56 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) -|57-84 | 28 |Spare | |x|Not used -|============================================================================== - -Air draught is the vertical distance measured from the ship's -waterline to the highest point on the ship. Air gap is the vertical -distance measured from the surface of the water to the sensor. - -The timestamp is for the forecast air gap. - -==== IMO289 Route Information (broadcast) ==== - -The content of this message is a time and a list of waypoints describing a -course. It has an addressed equivalent that is a message 6 subtype. - -A message 8 subtype. DAC = 001 FID = 27. Variable length: 172-997 bits. - -//: Type 8(1/27) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 27 -|56-65 | 10 |Message Linkage ID|linkage |u|Unsigned integer -|66-68 | 3 |Sender Class |sender |u|0 = ship (default), 1 = authority, - 27 = reserved for future use. -|69-73 | 5 |Route Type |rtype |e|See below -|74-77 | 4 |Start month |month |u|1-12, 0=N/A (default) -|78-82 | 5 |Start day |day |u|1-31, 0=N/A (default) -|83-87 | 5 |Start hour |hour |u|0-23, 24=N/A (default) -|88-93 | 6 |Start minute |minute |u|0-59, 60=N/A (default) -|94-111 | 18 |Duration |duration |u|Minutes from start time, - 0 = cancel route, - 262,143 = not available (default). -|112-116 | 5 |Waypoint count |waycount |u|1-16, values 17-31 are not used. -|117 | | |waypoints|a^16|Waypoint array -|0-27 | 28 |Longitude |lon |I4|Unit = minutes * 0.0001, - 181000 = N/A (default), - E positive, W negative. -|28-54 | 27 |Latitude |lat |I4|Unit = minutes * 0.001, - 91000 = N/A (default), - N positive, S negative. -|============================================================================== - -The final pair of fields in the table above is a waypoint. The message may -end with 1 to 16 waypoints. - -For interpretation of the Route Type field, see the table under the "Route -Information (addressed)" message (DAC=1, FID=28). - -==== IMO289 Text description (broadcast) ==== - -A message 8 subtype. DAC = 001 FID = 29. Variable length: 72-1032 bits. - -Intended to be used to associate a text annotation with another message -via the Message Linkage ID field. - -//: Type 8(1/29) -[frame="topbot",options="header"] -|============================================================================= -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 29 -|56-65 | 10 |Message Linkage ID|linkage |u|Unsigned integer -|66-? | 6-966 |Description |description|t|String -|============================================================================== - -There is an equivalent subtype of message 6 that is an addressed description. - -==== Meteorological and Hydrological Data (IMO289) === - -A message 8 subtype. DAC = 001 FID = 31. Fixed length, 360 bits. -Supersedes an <> message with the same title but FID = 11 and -a different binary layout. The exact differences are: (a) The -addition of the Position Accuracy field, (b) water level has 12 bits -of precision rather than 9 (units of centimeters rather than -decimeters), and (c) end padding changes from 6 to 10 bits. - -//: Type 8(1/31) -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |DAC |dac |u|DAC = 001 -|50-55 | 6 |FID |fid |u|FID = 31 -|56-80 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, - E positive, We negative, - 181000 = N/A (default). -|81-104 | 24 |Latitude |lat |I3|Unit = minutes * 0.001, - N positive, S negative, - 91000 = N/A (default). -|105-105 | 1 |Fix quality |accuracy |b|As in Common Navigation Block -|106-110 | 5 |Day |day |u|1-31, 0=N/A (default) -|111-115 | 5 |Hour |hour |u|0-23, 24=N/A (default) -|116-121 | 6 |Minute |minute |u|0-59, 60=N/A (default) -|122-128 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed: knots, - 126 = wind >= 126 knots, - 127 = N/A (default). -|129-135 | 7 |Gust Speed |wgust |u|10-min max wind speed: knots, - 126 = wind >= 126 knots, - 127 = N/A (default). -|136-144 | 9 |Wind Direction |wdir |u|0-359, true bearing, - 360 = N/A (default). -|145-153 | 9 |Wind Gust Direction|wgustdir |u|0-359, true bearing, - 360 = N/A (default). -|154-164 | 11 |Air Temperature |airtemp |I1|Dry bulb temp: units 0.1C, - -60.0 to +60.0, - -1024 = N/A (default). -|165-171 | 7 |Relative Humidity |humidity |u|0-100%: units of 1%, - 101 = N/A (default). -|172-181 | 10 |Dew Point |dewpoint |I1|-20.0 to +50.0: units 0.1C, - 501 = N/A (default). -|182-190 | 9 |Air Pressure |pressure |u|800-1200hPa, 1hPa, - 0 = pressure <= 799hPa, - 402 = pressure >= 1201 hPa, - 511 = N/A (default). -|191-192 | 2 |Pressure Tendency |pressuretend|e|0 = steady, - 1 = decreasing, - 2 = increasing, - 3 = N/A (default). -|193-193 | 7 |Max. visibility |visgreater |b|Visibility greater than. -|194-200 | 8 |Horiz. Visibility |visibility |U1|Units are 0.1 nautical miles, - 127 = N/A (default). -|201-212 | 12 |Water Level |waterlevel |I2|-10.0 to +30.0 in 0.01m, - -10.0m after scaling, - 4001 = N/A (default). -|213-214 | 2 |Water Level Trend |leveltrend |e|0 = steady, - 1 = decreasing, - 2 = increasing, - 3 = N/A (default). -|215-222 | 8 |Surface Current Speed |cspeed |U1|0.0-25.0: units 0.1 knot, - 251 = speed >= 25.1 knots, - 255 = N/A (default). -|223-231 | 9 |Surface Current Direction |cdir |u|0-359: deg. fom true north, - 360 = N/A (default). -|232-239 | 8 |Current Speed #2 |cspeed2 |U1|0.0-25.0 knots: - units 0.1 knot, - 251 = speed >= 25.1 knots, - 255 = N/A (default). -|240-248 | 9 |Current Direction #2 |cdir2 |u|0-359: true bearing, - 360 = N/A (default). -|249-253 | 5 |Measurement Depth #2 |cdepth2 |U1|0-30m down: units 0.1m, - 31 = N/A (default). -|254-261 | 8 |Current Speed #3 |cspeed3 |U1|0.0-25.0 knots: units 0.1 knot, - 251 = speed >= 25.1 knots, - 255 = N/A (default). -|262-270 | 9 |Current Direction #3 |cdir3 |u|0-359: true bearing, - 360 = N/A (default). -|271-275 | 5 |Measurement Depth #3 |cdepth3 |u|0-30m down: units 0.1m, - 31 = N/A (default). -|276-283 | 8 |Wave Height |waveheight|U1|Height 0-25m: units 0.1m, - 251 = height >= 25.1m, - 255 = N/A (default). -|284-289 | 6 |Wave Period |waveperiod|u|Seconds, 0-60, units 1s, - 63 = N/A (default). -|290-298 | 9 |Wave Direction |wavedir |u|0-359: true bearing, - 360 = N/A (default). -|299-306 | 8 |Swell Height |swellheight|U1|0-25m: units 0.1m, - 251 = height >= 25.1m, - 255 = N/A (default). -|307-312 | 6 |Swell Period |swellperiod|u|0-60, units 1s - 360 = N/A (default) -|313-321 | 9 |Swell Direction |swelldir |u|0-359: true bearing, - 360 = N/A (default) -|322-325 | 4 |Sea State |seastate |e|See "Beaufort scale" -|326-335 | 10 |Water Temperature |watertemp |I1|-10.0 to 50.0 C: - units 0.1 deg, - 501 = N/A (default) -|336-338 | 3 |Precipitation |preciptype |e|See "Precipitation type" -|339-347 | 9 |Salinity |salinity |U1|0.0-50.0%: units of 0.1% - 501 = salinity >= 50.1% - 510 = N/A (default) - 511 = sensor not available -|348-349 | 2 |Ice |ice |u| 0 = No - 1 = Yes - 2 = (reserved for future use) - 3 = not available = default -|350-359 | 10 |Spare | |x|Not used -|============================================================================== - -Precipitation types and Beaufort scale are as for the <> version. - -==== Inland ship static and voyage related data (Inland AIS) ==== - -A message 8 subtype. DAC = 200 FID = 10. Fixed length, 168 bits. - -This message should be used by inland vessels only to broadcast ship -static and voyage related data in addition to message 5. The message -should be sent as soon as possible (from the AIS point of view) after -message 5. - -//: Type 8(200/10) -[frame="topbot",options="header"] -|=============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |Designated Area Code |dac |u|Constant: 200 -|50-55 | 6 |Functional ID |fid |u|Constant: 10 -|56-103 | 48 |European Vessel ID |vin |t|8 six-bit characters -|104-116 | 13 |Length of ship |length |u|1-8000 * 0.1m, default 0 -|117-126 | 10 |Beam of ship |beam |u|1-1000 * 0.1m, default 0 -|127-140 | 14 |Ship/combination type |shiptype |e|ERI Classification -|141-143 | 3 |Hazardous cargo |hazard |e|See "Hazard Codes" below -|144-154 | 11 |Draught |draught |u|1-200 * 0.01m, default 0 -|155-156 | 2 |Loaded/Unloaded |loaded |e|See "Load Status" below -|157-157 | 1 |Speed inf. quality |speed_q |b|0 = low/GNSS (default) - 1 = high -|158-158 | 1 |Course inf. quality |course_q |b|0 = low/GNSS (default) - 1 = high -|159-159 | 1 |Heading inf. quality |heading_q|b|0 = low/GNSS (default) - 1 = high -|160-167 | 8 |Spare | |x|Not used -|============================================================================== - -OPEN-QUESTION: <> is not explicit whether the -"Ship/combination type" field is to contain full ERI codes with range -8000-8370 or ERI SOLAS codes in the range 1-99. The tables below -expand both. Full ERI codes have been observed in the wild. - -.ERI Classification -[frame="topbot",options="header"] -|============================================================================== -|Code | SOLAS | Description -|8000 | 99 | Vessel, type unknown -|8010 | 79 | Motor freighter -|8020 | 89 | Motor tanker -|8021 | 80 | Motor tanker, liquid cargo, type N -|8022 | 80 | Motor tanker, liquid cargo, type C -|8023 | 89 | Motor tanker, dry cargo as if liquid (e.g. cement) -|8030 | 79 | Container vessel -|8040 | 80 | Gas tanker -|8050 | 79 | Motor freighter, tug -|8060 | 89 | Motor tanker, tug -|8070 | 79 | Motor freighter with one or more ships alongside -|8080 | 89 | Motor freighter with tanker -|8090 | 79 | Motor freighter pushing one or more freighters -|8100 | 89 | Motor freighter pushing at least one tank-ship -|8110 | 79 | Tug, freighter -|8120 | 89 | Tug, tanker -|8130 | 31 | Tug freighter, coupled -|8140 | 31 | Tug, freighter/tanker, coupled -|8150 | 99 | Freightbarge -|8160 | 99 | Tankbarge -|8161 | 90 | Tankbarge, liquid cargo, type N -|8162 | 90 | Tankbarge, liquid cargo, type C -|8163 | 99 | Tankbarge, dry cargo as if liquid (e.g. cement) -|8170 | 99 | Freightbarge with containers -|8180 | 90 | Tankbarge, gas -|8210 | 79 | Pushtow, one cargo barge -|8220 | 79 | Pushtow, two cargo barges -|8230 | 79 | Pushtow, three cargo barges -|8240 | 79 | Pushtow, four cargo barges -|8250 | 79 | Pushtow, five cargo barges -|8260 | 79 | Pushtow, six cargo barges -|8270 | 79 | Pushtow, seven cargo barges -|8280 | 79 | Pushtow, eight cargo barges -|8290 | 79 | Pushtow, nine or more barges -|8310 | 80 | Pushtow, one tank/gas barge -|8320 | 80 | Pushtow, two barges at least one tanker or gas barge -|8330 | 80 | Pushtow, three barges at least one tanker or gas barge -|8340 | 80 | Pushtow, four barges at least one tanker or gas barge -|8350 | 80 | Pushtow, five barges at least one tanker or gas barge -|8360 | 80 | Pushtow, six barges at least one tanker or gas barge -|8370 | 80 | Pushtow, seven barges at least one tanker or gas barge -|============================================================================= - -.SOLAS ship type, first digit -[frame="topbot",options="header"] -|============================================================================= -| 3 | Vessel -| 7 | Cargo ship -| 8 | Tanker -| 9 | Other types of ship -|============================================================================= - -.SOLAS ship type, second digit -[frame="topbot",options="header"] -|============================================================================= -| 0 | All ships of this type -| 1 | Towing -| 8 | Tanker -| 9 | No additional information -|============================================================================= - -.Hazard code -[frame="topbot",options="header"] -|============================================================================== -| 0 | 0 blue cones/lights -| 1 | 1 blue cone/light -| 2 | 2 blue cones/lights -| 3 | 3 blue cones/lights -| 4 | 4 B-Flag -| 5 | Unknown (default) -|============================================================================== - -.Load status -[frame="topbot",options="header"] -|============================================================================== -| 0 | N/A (default) -| 1 | Unloaded -| 2 | Loaded -|============================================================================== - -==== EMMA Warning Report (Inland AIS) ==== - -A message 8 subtype. DAC = 200 FID = 23. Fixed length, 256 bits. - -The EMMA warning is sent by base stations to drive shipboard ECDIS -displays of heavy weather conditions. The following message is capable -of transmitting the EMMA data using the AIS channel. It does not -replace the Notices to Skippers warnings. - -//: Type 8(200/23) -[frame="topbot",options="header"] -|=============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |Designated Area Code|dac |u|Constant: 200 -|50-55 | 6 |Functional ID |fid |u|Constant: 23 -|56-63 | 8 |Start Year |start_year |u|1-55, year since 2000 - 0 = N/A (default) -|64-67 | 4 |Start Month |start_month |u|1-12; 0 = N/A (default) -|68-72 | 5 |Start Day |start_day |u|1-31; 0 = N/A (default) -|73-80 | 8 |End Year |end_year |u|1-55, year since 2000 - 0 = N/A (default) -|81-84 | 4 |End Month |end_month |u|1-12; 0 = N/A (default) -|85-89 | 5 |End Day |end_day |u|1-31; 0 = N/A (default) -|90-94 | 5 |Start Hour |start_hour |u|0-23; 24 = N/A (default) -|95-100 | 6 |Start Minute |start_minute|u|0-59; 60 = N/A (default) -|101-105 | 5 |End Hour |end_hour |u|0-23; 24 = N/A (default) -|106-111 | 6 |End Minute |end_minute |u|0-59; 60 = N/A (default) -|112-139 | 28 |Start Longitude |start_lon |I4|Minutes/10000 (as in CNB) -|140-166 | 27 |Start Latitude |start_lat |I4|Minutes/10000 (as in CNB) -|167-194 | 28 |End Longitude |end_lon |I4|Minutes/10000 (as in CNB) -|195-221 | 27 |End Latitude |end_lat |I4|Minutes/10000 (as in CNB) -|222-225 | 4 |Type |type |e|See "EMMA Type Codes" below -|226-234 | 9 |Min value |min |i|Signed Integer, see below -|235-243 | 9 |Max value |max |i|Signed Integer, see below -|244-245 | 2 |Classification |intensity |e|1 = Slight, - 2 = Medium, - 3 = Strong -|246-249 | 4 |Wind Direction |wind |e|See "EMMA Winds" below -|250-255 | 6 |Spare | |x|Not used -|=============================================================================== - -OPEN-QUESTION: <> is not explicit about the interpretation of -the longitude and latitude fields; these semantics are assumed here -from 28 and 27-bit fields in other messages. - -<> specifies an 8-bit format with 9th leading sign bit for the -min and max fields. Values 0-253 are interpreted as integer data, -modified by the leading sign bit. The values +254 and -254 are -interpreted as "greater that +253" and "less than -253" respectively. -Both values +255 and -255 are interpreted as "unknown" (default). - -OPEN-QUESTION: What are the semantics of the min and max values? To -what parameters do they apply? - -OPEN-QUESTION: <> does not specify whether start and end times -are UTC or local. - -.EMMA Type Codes -[frame="topbot",options="header"] -|============================== -| 0 | NA | Not Available -| 1 | WI | Wind -| 2 | RA | Rain -| 3 | SN | Snow and ice -| 4 | TH | Thunderstorm -| 5 | FO | Fog -| 6 | LT | Low temperature -| 7 | HT | High temperature -| 8 | FL | Flood -| 9 | FI | Forest Fire -|============================== - -.EMMA Winds -[frame="topbot",options="header"] -|============================== -| 1 | N | North -| 2 | NE | North East -| 3 | E | East -| 4 | SE | South East -| 5 | S | South -| 6 | SW | South West -| 7 | W | West -| 8 | NW | North West -|============================== - -==== Water Levels (Inland AIS) ==== - -A message 6 subtype. DAC = 200 FID = 24. Fixed length, 168 bits. - -This message should be used to inform skippers about actual water -levels in their area. It is additional short-term information to the -water levels distributed via Notices to Skippers. It is possible to -transmit the water levels of more than 4 gauges using multiple -messages. - -//: Type 8(200/24) -[frame="topbot",options="header"] -|=============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 6 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |Designated Area Code|dac |u|Constant: 200 -|50-55 | 6 |Functional ID |fid |u|Constant: 24 -|56-67 | 12 |UN Country Code |country |t|2 six-bit characters -|68 | | |gauges |a4|Gauge measurement array -|0-10 | 11 |Gauge ID |id |u|0=unknown (default) -|11-24 | 14 |Water Level |level |i|cm, 0=unknown (default) -|=============================================================================== - -Water levels are relative to the local standard, e.g. GIW in Germany -and RNW on the Danube. - -==== Signal Strength (Inland AIS) ==== - -A message 8 subtype. DAC = 200 FID = 40. Fixed length, 168 bits. - -This message should be sent by base stations only, to inform about the -status of different light signals to all vessels in a certain -area. The information should be displayed on an external Inland ECDIS -display as dynamic symbols. The message should be sent with binary -message 8 at regular intervals. - -//: Type 8(200/40) -[frame="topbot",options="header"] -|=============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 8 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-49 | 10 |Designated Area Code|dac |u|Constant: 200 -|50-55 | 6 |Functional ID |fid |u|Constant: 40 -|56-83 | 28 |Signal Longitude |lon |I4|Minutes/10000 (as in CNB) -|84-110 | 27 |Signal Latitude |lat |I4|Minutes/10000 (as in CNB) -|111-114 | 4 |Signal form |form |u|Consult <> Annex C -|115-123 | 9 |Signal orientation |facing |u|0-39 deg, 511= N/A (default) -|124-126 | 3 |Direction of impact |direction |e|See "Signal Impact" below -|127-156 | 30 |Light Status |status |e|See "Signal Status" below -|157-167 | 11 |Spare | |x|Not used -|=============================================================================== - -OPEN-QUESTION: <> is not explicit about the interpretation of -the longitude and latitude fields; these semantics are assumed here -from 28 and 27-bit fields in other messages. - -The Signal Form field describes the physical arrangement of the -signal lights. Values 0 and 15 indicate the shape is unknown or -unspecified. - -//: direction vocabulary -.Direction of Signal Impact -[frame="topbot",options="header"] -|=============================================================================== -| 0 | Unknown (default) -| 1 | Upstream -| 2 | Downstream -| 3 | To left bank -| 4 | To right bank -|=============================================================================== - -The Signal Status field is interpreted as 9 decimal digits describing -the lights as numbered in their Signal Form diagram - typically left -to right and then top to bottom - with each digit interpreted in the -following way: - -//: status vocabulary -.Signal Status -[frame="topbot",options="header"] -|=============================================================================== -| 0 | Unknown (default) -| 1 | No light -| 2 | White -| 3 | Yellow -| 4 | Green -| 5 | Red -| 6 | White flashing -| 7 | Yellow flashing. -|=============================================================================== - -=== Type 9: Standard SAR Aircraft Position Report === - -Tracking information for search-and-rescue aircraft. Total number of -bits is 168. - -//: Type 9 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Encoding -|0-5 | 6 |Message Type |type |u|Constant: 9 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 |30 |MMSI |mmsi |u|9 decimal digits -|38-49 |12 |Altitude |alt |u|See below -|50-59 |10 |SOG |speed |u|See below -|60-60 | 1 |Position Accuracy |accuracy |u|See below -|61-88 |28 |Longitude |lon |I4|Minutes/10000 (as in CNB) -|89-115 |27 |Latitude |lat |I4|Minutes/10000 (as in CNB) -|116-127 |12 |Course Over Ground |course |U1|True bearing, 0.1 degree units -|128-133 | 6 |Time Stamp |second |u|UTC second. -|134-141 | 8 |Regional reserved |regional |x|Reserved -|142-142 | 1 |DTE |dte |b|0=Data terminal ready, - 1=Data terminal not ready (default) -|143-145 | 3 |Spare | |x|Not used -|146-146 | 1 |Assigned |assigned |b|Assigned-mode flag -|147-147 | 1 |RAIM flag |raim |b|As for common navigation block -|148-167 |20 |Radio status |radio |u|See <> for details. -|============================================================================== - -Altitude is in meters. The special value 4095 indicates altitude is -not available; 4094 indicates 4094 meters or higher. - -Speed over ground is in knots, not deciknots as in the common -navigation block; planes go faster. The special value 1023 indicates -speed not available, 1022 indicates 1022 knots or higher. - -Position Accuracy, Longitude, Latitude, and Course over Ground -are encoded identically as in the common navigation block and -are even at the same bit offsets. Time stamp has the same special -values as in the common navigation block, but is at a different offset. - -=== Type 10: UTC/Date Inquiry === - -Request for UTC/Date information from an AIS base station. Total -number of bits is 72. - -//: Type 10 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Encoding -|0-5 | 6 |Message Type |type |u|Constant: 10 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 |30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-69 |30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70-71 | 2 |Spare | |x|Not used -|============================================================================== - -=== Type 11: UTC/Date Response === - -Identical to message 4, with the semantics of a response to inquiry. - -=== Type 12: Addressed Safety-Related Message === - -This is a point-to-point text message. The payload is interpreted as -six-bit text. This message is variable in length up to a maximum of -1008 bits (up to 5 AIVDM sentence payloads). - -//: Type 12 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 12 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Sequence Number |seqno |u|Unsigned integer 0-3 -|40-69 | 30 |Destination MMSI |dest_mmsi |u|9 decimal digits -|70 | 1 |Retransmit flag |retransmit |b|0 = no retransmit (default), - 1 = retransmitted -|71 | 1 |Spare | |x|Not used -|72 |936 |Text |text |t|1-156 chars of six-bit text. - May be shorter than 936 bits. -|============================================================================== - -Pragmatic note: On <<>> the actual content of these messages is -highly variable, ranging from fairly plain English ("PLEASE REPORT TO -JOBOURG TRAFFIC CHANNEL 13") through snippets of tabular data ("PAX -589 FG 36 IX 74 MOTO 10 CREW 108+1" through what look like opaque -commercial codes ("EP285 IX46 FG3 DK8 PL56") to empty strings and -content that looks like line noise ("]XFD5D/\7`>PA!Q DX0??K?8?>D"). - -Such apparently garbled content does *not* mean there is an error in -your decoder. It may indicate faulty encoders, operator error, or even -the use of private encodings for non-ASCII character sets. - -=== Type 13: Safety-Related Acknowledgement === - -Message type 13 is a receipt acknowledgement to senders of -previous messages of type 12. The message layout is identical to -a type 7 Binary Acknowledge. - -=== Type 14: Safety-Related Broadcast Message === - -This is a broadcast text message. The payload is interpreted as -six-bit text. This message is variable in length up to a maximum of -1008 bits (up to 5 AIVDM sentence payloads). - -//: Type 14 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 14 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40 |968 |Text |text |t|1-161 chars of six-bit text. - May be shorter than 968 bits. -|============================================================================== - -Note: 161 * 6 = 966. <> specifies 968 because over-the-air -messages are required to be padded to an 8-bit byte boundary by -<<>>. - -Also see the pragmatic note on message content attached to type 12; it -applies to type 14 messages as well. - -=== Type 15: Interrogation === - -Message type 15 is used by a base station to query one or two other AIS -transceivers for status messages of specified types. "Source MMSI" is -the interrogating station. 88-160 bits depending on the number of queries. - -This message is probably not interesting unless you are doing traffic -analysis of information flow in an AIS station network. The "slot offset" -members are a request for the response to interrogation to occupy -a particular time division in the TDMA packet layer. - -//: Type 15 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 15 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-69 | 30 |Interrogated MMSI |mmsi1 |u|9 decimal digits -|70-75 | 6 |First message type |type1_1 |u|Unsigned integer -|76-87 | 12 |First slot offset |offset1_1 |u|Unsigned integer -|88-89 | 2 |Spare | |x|Not used -|90-95 | 6 |Second message type |type1_2 |u|Unsigned integer -|96-107 | 12 |Second slot offset |offset1_2 |u|Unsigned integer -|108-109 | 2 |Spare | |x|Not used -|110-139 | 30 |Interrogated MMSI |mmsi2 |u|9 decimal digits -|140-145 | 6 |First message type |type2_1 |u|Unsigned integer -|146-157 | 12 |First slot offset |offset2_1 |u|Unsigned integer -|158-159 | 2 |Spare | |x|Not used -|============================================================================== - -There are four use cases for this message. A decoder must dispatch on -the length of the data packet to determine which it is seeing: - -1. One station is interrogated for one message type. Length is 88 bits. - -2. One station is interrogated for two message types, Length is 110 -bits. There is a design error in the standard here; according to the -<<>> requirement for padding to 8 bits, this should have been -112 with a 4-bit trailing spare field, and decoders should be prepared -to handle that length as well. See the discussion of byte alignment -elsewhere in this document for context. - -3. Two stations are interrogated for one message type each. Length is -160 bits. The second message type and second slot offset associated -with the first queried MMSI should be zeroed. - -4. One station is interrogated for two message types, and a second for -one message type. Length is 160 bits. - -=== Type 16: Assignment Mode Command === - -Message type 16 is used by a base station with control authority to -configure the scheduling of AIS informational messages from -subordinate stations, either as a frequency per 10-minute interval or -by specifying the TDMA slot(s) offset on which those messages should -be transmitted. It is probably not of interest unless you are -studying the internal operation of an AIS base station network. -Length may be 96 or 144 bits. - -//: Type 16 -[frame="topbot",options="header"] -|============================================================================ -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 16 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-69 | 30 |Destination A MMSI |mmsi1 |u|9 decimal digits -|70-81 | 12 |Offset A |offset1 |u|See <> -|82-91 | 10 |Increment A |increment1 |u|See <> -|92-121 | 30 |Destination B MMSI |mmsi2 |u|9 decimal digits -|122-133 | 12 |Offset B |offset2 |u|See <> -|134-143 | 10 |Increment B |increment2 |u|See <> -|============================================================================= - -If the message is 96 bits long, it should be interpreted as an -assignment for a single station (92 bits) followed by 4 bits of -padding reserved for future use. If the message is 144 bits long it -should be interpreted as a channel assignment for two stations; no -padding follows. - -When increment is zero, the offset field is interpreted as the -frequency with which the subordinate station should report per -10-minute interval. When increment is nonzero, reporting interval -is specified at the level of TDMA slot numbers; see <> for the -detailed specification. - -Note: While the 96-bit form of Type 16 is not uncommon, the 144-bit -form is extremely rare. As of March 2010 it has not been observed even -in long-duration samples from AISHub. - -=== Type 17: DGNSS Broadcast Binary Message === - -Message type 17 is used to broadcast differential corrections for GPS. -The data in the payload is intended to be passed directly to GPS -receivers capable of accepting such corrections. 80 to 816 bits -depending on payload size. - -//: Type 17 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 17 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 | 30 |Source MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-57 | 18 |Longitude |lon |I1|Signed: minutes/10 -|58-74 | 17 |Latitude |lat |I1|Signed: minutes/10 -|75-79 | 5 |Spare | |x|Not used - reserved -|80-815 |736 |Payload |data |d|DGNSS correction data -|============================================================================== - -Note that latitude and longitude are in units of a tenth of a minute; -sign interpretation and out-of-band values are as in the Common -Navigation Clock. (Note, however, that the hex representation of -the out-of-band values differs; it is 181 \* 60 \* 10 = 0x1a838 for -longitude, 91 \* 60 \* 10 = 0xd548 for latitude.) - -The <> description of the payload portion subfields has been -omitted, as it appears to be tied to the now obsolete RTCM2 protocol. - -=== Type 18: Standard Class B CS Position Report === - -A less detailed report than types 1-3 for vessels using Class B -transmitters. Omits navigational status and rate of turn. Fields are -encoded as in the common navigation block. 168 bits total. - -In <> (and <>) bits 141-145 were designated "Spare"; the -bit-flag semantics given here are from ITU-1371-3 and were -communicated by Kurt Schwehr. Kurt warns that "the spec does not do a -good job of explaining these fields... I don't think that I totally -understand these fields." - -//: Type 18 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 18 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 |30 |MMSI |mmsi |u|9 decimal digits -|38-45 | 8 |Regional Reserved |reserved |x|Not used -|46-55 |10 |Speed Over Ground |speed |U1|As in common navigation block -|56-56 | 1 |Position Accuracy |accuracy |b|See below -|57-84 |28 |Longitude |lon |I4|Minutes/10000 (as in CNB) -|85-111 |27 |Latitude |lat |I4|Minutes/10000 (as in CNB) -|112-123 |12 |Course Over Ground |course |U1|0.1 degrees from true north -|124-132 | 9 |True Heading |heading |u|0 to 359 degrees, 511 = N/A -|133-138 | 6 |Time Stamp |second |u|Second of UTC timestamp. -|139-140 | 2 |Regional reserved |regional |u|Uninterpreted -|141-141 | 1 |CS Unit |cs |b|0=Class B SOTDMA unit - 1=Class B CS (Carrier Sense) unit -|142-142 | 1 |Display flag |display |b|0=No visual display, - 1=Has display, - (Probably not reliable). -|143-143 | 1 |DSC Flag |dsc |b|If 1, unit is attached to a VHF - voice radio with DSC capability. -|144-144 | 1 |Band flag |band |b|Base stations can command units - to switch frequency. If this flag - is 1, the unit can use any part - of the marine channel. -|145-145 | 1 |Message 22 flag |msg22 |b|If 1, unit can accept a channel - assignment via Message Type 22. -|146-146 | 1 |Assigned |assigned |b|Assigned-mode flag: - 0 = autonomous mode (default), - 1 = assigned mode. -|147-147 | 1 |RAIM flag |raim |b|As for common navigation block -|148-167 |20 |Radio status |radio |u|See <> for details. -|============================================================================== - -The radio status is 20 bits rather than 19 because an extra first bit -selects whether it should be interpreted as a SOTDMA or ITDMA state. - -=== Type 19: Extended Class B CS Position Report === - -A slightly more detailed report than type 18 for vessels using Class B -transmitters. Omits navigational status and rate of turn. Fields are -encoded as in the common navigation block and the Type 5 message. -Note that until just before the reserved field at bit 139 this is -identical to message 18. 312 bits total. - -In practice, the information in the ship name and dimension fields is -not reliable, as it has to be hand-entered by humans rather than -gathered automatically from sensors. - -//: Type 19 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 19 -|6-7 | 2 |Repeat Indicator |repeat |u|As in CNN -|8-37 | 30 |MMSI |mmsi |u|9 digits -|38-45 | 8 |Regional Reserved |reserved |u| -|46-55 | 10 |Speed Over Ground |speed |U1|As in CNB. -|56-56 | 1 |Position Accuracy |accuracy |b|As in CNB. -|57-84 | 28 |Longitude |lon |I4|Minutes/10000 (as in CNB) -|85-111 | 27 |Latitude |lat |I4|Minutes/10000 (as in CNB) -|112-123 | 12 |Course Over Ground |course |U1|Relative to true north, - units of 0.1 degrees -|124-132 | 9 |True Heading |heading |u|0 to 359 degrees, - 511 = N/A -|133-138 | 6 |Time Stamp |second |u|Second of UTC timestamp. -|139-142 | 4 |Regional reserved |regional |u|Uninterpreted -|143-262 |120 |Name |shipname |s|20 6-bit characters -|263-270 | 8 |Type of ship and cargo |shiptype |u|As in Message 5 -|271-279 | 9 |Dimension to Bow |to_bow |u|Meters -|280-288 | 9 |Dimension to Stern |to_stern |u|Meters -|289-294 | 6 |Dimension to Port |to_port |u|Meters -|295-300 | 6 |Dimension to Starboard |to_starboard |u|Meters -|301-304 | 4 |Position Fix Type |epfd |e|See "EPFD Fix Types" -|305-305 | 1 |RAIM flag |raim |b|As in CNB. -|306-306 | 1 |DTE |dte |b|0=Data terminal ready, - 1=Not ready (default). -|307-307 | 1 |Assigned mode flag |assigned |u|See <> for details -|308-311 | 4 |Spare | |x|Unused, should be zero -|============================================================================== - -=== Type 20 Data Link Management Message === - -This message is used to pre-allocate TDMA slots within an AIS base -station network. It contains no navigational information, and is -unlikely to be of interest unless you are implementing or studying -an AIS base station network. Length varies from 72-160 depending on -the number of slot reservations (1 to 4) in the message. - -//: Type 20 -[frame="topbot",options="header"] -|=============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 20 -|6-7 | 2 |Repeat Indicator |repeat |u|As in CNB -|8-37 |30 |MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-51 |12 |Offset number 1 |offset1 |u|Reserved offset number -|52-55 | 4 |Reserved slots |number1 |u|Consecutive slots -|56-58 | 3 |Time-out |timeout1 |u|Allocation timeout in minutes -|59-69 |11 |Increment |increment1 |u|Repeat increment -|70-81 |12 |Offset number 2 |offset2 |u|Reserved offset number -|82-85 | 4 |Reserved slots |number2 |u|Consecutive slots -|86-88 | 3 |Time-out |timeout2 |u|Allocation timeout in minutes -|89-99 |11 |Increment |increment2 |u|Repeat increment -|100-111 |12 |Offset number 3 |offset3 |u|Reserved offset number -|112-115 | 4 |Reserved slots |number3 |u|Consecutive slots -|116-118 | 3 |Time-out |timeout3 |u|Allocation timeout in minutes -|119-129 |11 |Increment |increment3 |u|Repeat increment -|130-141 |12 |Offset number 4 |offset4 |u|Reserved offset number -|142-145 | 4 |Reserved slots |number4 |u|Consecutive slots -|146-148 | 3 |Time-out |timeout4 |u|Allocation timeout in minutes -|149-159 |11 |Increment |increment4 |u|Repeat increment -|=============================================================================== - -See <> for details on the meaning of these fields. - -=== Type 21: Aid-to-Navigation Report === - -Identification and location message to be emitted by aids to -navigation such as buoys and lighthouses. - -This message is unusual in that it varies in length depending on the -presence and size of the Name Extension field. May vary between 272 -and 360 bits. - -//: Type 21 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 21 -|6-7 | 2 |Repeat Indicator |repeat |u|As in CNB -|8-37 |30 |MMSI |mmsi |u|9 digits -|38-42 | 5 |Aid type |aid_type |e|See "Navaid Types" -|43-162 1|120 |Name |name |t|Name in sixbit chars -|163-163 | 1 |Position Accuracy |accuracy |b|As in CNB -|164-191 |28 |Longitude |lon |I4|Minutes/10000 (as in CNB) -|192-218 |27 |Latitude |lat |I4|Minutes/10000 (as in CNB) -|219-227 | 9 |Dimension to Bow |to_bow |u|Meters -|228-236 | 9 |Dimension to Stern |to_stern |u|Meters -|237-242 | 6 |Dimension to Port |to_port |u|Meters -|243-248 | 6 |Dimension to Starboard |to_starboard|u|Meters -|249-252 | 4 |Type of EPFD |epfd |e|As in Message Type 4 -|253-258 | 6 |UTC second |second |u|As in Message Types 1-3 -|259-259 | 1 |Off-Position Indicator |off_position|b|See Below -|260-267 | 8 |Regional reserved |regional |u|Uninterpreted -|268-268 | 1 |RAIM flag |raim |b|As in CNB -|269-269 | 1 |Virtual-aid flag |virtual_aid |b|See Below -|270-270 | 1 |Assigned-mode flag |assigned |b|See <> for details -|271-271 | 1 |Spare | |x|Not used -|272-360 |88 |Name Extension | |t|See Below -|============================================================================== - -According to <>, the aid type field has values 1-15 for fixed -and 16-31 for floating aids to navigation. The detailed list is as follows: - -.Navaid Types -[frame="topbot",options="header"] -|==================================================================== -|Code |Definition -|0 |Default, Type of Aid to Navigation not specified -|1 |Reference point -|2 |RACON (radar transponder marking a navigation hazard) -|3 |Fixed structure off shore, such as oil platforms, wind farms, -| rigs. (Note: This code should identify an obstruction that is -| fitted with an Aid-to-Navigation AIS station.) -|4 |Spare, Reserved for future use. -|5 |Light, without sectors -|6 |Light, with sectors -|7 |Leading Light Front -|8 |Leading Light Rear -|9 |Beacon, Cardinal N -|10 |Beacon, Cardinal E -|11 |Beacon, Cardinal S -|12 |Beacon, Cardinal W -|13 |Beacon, Port hand -|14 |Beacon, Starboard hand -|15 |Beacon, Preferred Channel port hand -|16 |Beacon, Preferred Channel starboard hand -|17 |Beacon, Isolated danger -|18 |Beacon, Safe water -|19 |Beacon, Special mark -|20 |Cardinal Mark N -|21 |Cardinal Mark E -|22 |Cardinal Mark S -|23 |Cardinal Mark W -|24 |Port hand Mark -|25 |Starboard hand Mark -|26 |Preferred Channel Port hand -|27 |Preferred Channel Starboard hand -|28 |Isolated danger -|29 |Safe Water -|30 |Special Mark -|31 |Light Vessel / LANBY / Rigs -|==================================================================== - -The name field is up to 20 characters of 6-bit ASCII. If this field -is full (has no trailing @ characters) the decoder should interpret -the Name Extension field later in the message (no more than 14 6-bit -characters) and concatenate it to this one to obtain the full name. - -<> describes bits 219-248 As "Dimension/Reference for Position", -implying that it is vessel dimensions as in message type 5. - -The Off-Position Indicator is for floating Aids-to-Navigation only: 0 -means on position; 1 means off position. Only valid if UTC second is equal to -or below 59. - -The Virtual Aid flag is interpreted as follows: 0 = default = real Aid -to Navigation at indicated position; 1 = virtual Aid to -Navigation simulated by nearby AIS station. - -If present, the Name Extension consists of packed six-bit ASCII -characters followed by 0-6 bits of padding to an 8-bit boundary. The -<> description says "This parameter should be omitted when no -more than 20 characters for the name of the A-to-N are needed in -total. Only the required number of characters should be transmitted, -i.e. no @-character should be used." A decoder can deduce the bit length -of the name extension field by subtracting 272 from the total message -bit length. - -=== Type 22: Channel Management === - -This message is broadcast by a competent authority (an AIS network -control base station) to set VHF parameters for an AIS coverage -region. Length is 168 bits. - -This message contains no navigational information, and is unlikely to be of -interest unless you are implementing or studying an AIS base station -network. - -//: Type 22 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Constant: 22 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 |30 |MMSI |mmsi |u|9 decimal digits -|38-39 | 2 |Spare | |x|Not used -|40-51 |12 |Channel A |channel_a |u|Channel number -|52-63 |12 |Channel B |channel_b |u|Channel number -|64-67 | 4 |Tx/Rx mode |txrx |u|Transmit/receive mode -|68-68 | 1 |Power |power |b|Low=0, high=1 -|69-86 |18 |NE Longitude |ne_lon |I1|NE longitude to 0.1 minutes -|87-103 |17 |NE Latitude |ne_lat |I1|NE latitude to 0.1 minutes -|104-121 |18 |SW Longitude |sw_lon |I1|SW longitude to 0.1 minutes -|122-138 |17 |SW Latitude |sw_lat |I1|SW latitude to 0.1 minutes -|69-98 |30 |MMSI1 |dest1 |u|MMSI of destination 1 -|104-133 |30 |MMSI2 |dest2 |u|MMSI of destination 2 -|139-139 | 1 |Addressed |addressed |b|0=Broadcast, 1=Addressed -|140-140 | 1 |Channel A Band |band_a |b|0=Default, 1=12.5kHz -|141-141 | 1 |Channel B Band |band_b |b|0=Default, 1=12.5kHz -|142-144 | 3 |Zone size |zonesize |u|Size of transitional zone -|145-167 |23 |Spare | |x|Reserved for future use -|============================================================================== - -The values of the channel_a and channel_b fields are ITU frequency -designators for channels A and B. Normally these will be 2087 and -2088, the AIS 1 and AIS 2 frequencies of 87B (161.975 MHz) and 88B -(162.025 MHz) respectively. Regional authorities may set different -frequencies. - -The txrx field encodes the same information as the 2-bit field txrx -field in message type 23; only the two low bits are used. - -The power bit instructs designated receivers which power level to use. - -If the message is broadcast (addressed field is 0), the ne_lon, -ne_lat, sw_lon, and sw_lat fields are the corners of a rectangular -jurisdiction area over which control parameters are to be set. If it -is addressed (addressed field is 1), the same span of data is -interpreted as two 30-bit MMSIs beginning at at bit offsets 69 and 104 -respectively. - -Yes, the addressed bit is *after* the fields it controls the -interpretation of. - -Note that the 'not available' values for longitude and latitudes -match the short ones used in message 17, not the long ones used in the -common navigation block and elsewhere. - -The band fields control channel bandwidth for channels A and B, and -the zonesize field describes the size of the transition zone around the -control jurisdiction. The semantics of these fields are complicated, -controlling transmitter behavior as it moves between jurisdictions; -see <> for full details. - -=== Type 23: Group Assignment Command === - -This message is intended to be broadcast by a competent authority (an -AIS network-control base station) to set operational parameters for -all mobile stations in an AIS coverage region. Length is 160 bits. - -This message contains no navigational information, and is unlikely to -be of interest unless you are implementing or studying an AIS base -station network. - -//: Type 23 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |T|Units -|0-5 | 6 |Message Type |type |u|Unsigned Integer: 23 -|6-7 | 2 |Repeat Indicator |repeat |u|As in Common Navigation Block -|8-37 |30 |MMSI |mmsi |u|Unsigned Integer: 9 digits -|38-39 | 2 |Spare | |x|Not used -|40-57 |18 |NE Longitude |ne_lon |u|Same as broadcast type 22 -|58-74 |17 |NE Latitude |ne_lat |u|Same as broadcast type 22 -|75-92 |18 |SW Longitude |sw_lon |u|Same as broadcast type 22 -|93-109 |17 |SW Latitude |sw_lat |u|Same as broadcast type 22 -|110-113 | 4 |Station Type |station_type |e|See "Station Types" -|114-121 | 8 |Ship Type |ship_type |e|See "Ship Types" -|122-143 |22 |Spare | |x|Not used -|144-145 | 2 |Tx/Rx Mode |txrx |u|See "Tranmit/Recieve Modes" -|146-149 | 4 |Report Interval |interval |e|See "Station Intervals" -|150-153 | 4 |Quiet Time |quiet |u|0 = none, 1-15 quiet time in minutes -|154-159 | 6 |Spare | |x|Not used -|============================================================================== - -The target set of mobile stations is specified by the station-type and -ship-type fields. An addressed (non-broadcast) message 22 overrides a -message 23, but a message 23 overrides a broadcast message 22. - -Note that the 'not available' values for longitude and latitudes -match the short ones used in messages 17 and 22, not the long ones -used in the common navigation block and elsewhere. - -The txrx field tells the affected stations which channel or -channels they may transmit on. The options refer to the same A and B -VHF channels as in Message Type 22. The field is interpreted as follows: - -.Transmit Modes -[width="25%",frame="topbot"] -|=================================== -|0 = |TxA/TxB, RxA/RxB (default) -|1 = |TxA, RxA/RxB -|2 = |TxB, RxA/RxB -|3 = |Reserved for Future Use -|=================================== - -.Station Types -[width="50%",frame="topbot"] -|====================================================== -|0 |All types of mobiles (default) -|1 |Reserved for future use -|2 |All types of Class B mobile stations -|3 |SAR airborne mobile station -|4 |Aid to Navigation station -|5 |Class B shipborne mobile station (IEC62287 only) -|6-9 |Regional use and inland waterways -|10-15 |Reserved for future use -|====================================================== - -<> specifies 6 (only) as the station type value for inland -waterways, reserving 7-9 for (other) regional uses. - -Reporting Interval is a 4 bit unsigned integer, how often to report -while within the area specified by this message. When the dual-channel -operation is suspended by Tx/Rx mode command 1 or 2, the reporting -interval is twice the interval given in the table. - -.Station Intervals -[width="50%",frame="topbot"] -|====================================================== -|0 |As given by the autonomous mode -|1 |10 Minutes -|2 |6 Minutes -|3 |3 Minutes -|4 |1 Minute -|5 |30 Seconds -|6 |15 Seconds -|7 |10 Seconds -|8 |5 Seconds -|9 |Next Shorter Reporting Interval -|10 |Next Longer Reporting Interval -|11-15 |Reserved for future use -|====================================================== - -Quiet Time is a 4 bit unsigned integer specifying how many minutes -affected stations are to remain silent. If a class B station receives -a quiet time command, it will continue to schedule nominal -transmission time periods, but is not to transmit message 18 or 24 -during the quiet period. - -=== Type 24: Static Data Report === - -Equivalent of a Type 5 message for ships using Class B equipment. Also -used to associate an MMSI with a name on either class A or class B equipment. - -A "Type 24" may be in part A or part B format; According to the -standard, parts A and B are expected to be broadcast in adjacent -pairs; in the real world they may (due to quirks in various -aggregation methods) be separated by other sentences or even -interleaved with different Type 24 pairs; decoders must cope with -this. The interpretation of some fields in Type B format changes -depending on the range of the Type B MMSI field. 160 bits for part A, -168 bits for part B. - -According to the standard, both the A and B parts are supposed to -be 168 bits. However, in the wild, A parts are often transmitted -with only 160 bits, omitting the 'spare' 7 bits at the end. -Implementers should be permissive about this. - -<> does not describe this message type; format information -is thanks to Kurt Schwehr. - -//: Type 24 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description | Member |T|Units -|0-5 | 6 | Message Type | type |u|Constant: 24 -|6-7 | 2 | Repeat Indicator | repeat |u|As in CNB -|8-37 | 30 | MMSI | mmsi |u|9 digits -|38-39 | 2 | Part Number | partno |u|0-1 -|40-159 |120 | Vessel Name | shipname |t|(Part A) 20 sixbit chars -|160-167 | 8 | Spare | |x|(Part A) Not used -|40-47 | 8 | Ship Type | shiptype |e|(Part B) See "Ship Types" -|48-65 | 18 | Vendor ID | vendorid |t|(Part B) 3 six-bit chars -|66-69 | 4 | Unit Model Code | model |u|(Part B) -|70-89 | 20 | Serial Number | serial |u|(Part B) -|90-131 | 42 | Call Sign | callsign |t|(Part B) As in Message Type 5 -|132-140 | 9 | Dimension to Bow | to_bow |u|(Part B) Meters -|141-149 | 9 | Dimension to Stern | to_stern |u|(Part B) Meters -|150-155 | 6 | Dimension to Port | to_port |u|(Part B) Meters -|156-161 | 6 | Dimension to Starboard| to_starboard |u|(Part B) Meters -|132-161 | 30 | Mothership MMSI | mothership_mmsi|u|(Part B) See below -|162-167 | 6 | Spare | |x|(Part B) Not used -|=============================================================================== - -If the Part Number field is 0, the rest of the message is interpreted -as a Part A; if it is 1, the rest of the message is interpreted -as a Part B; values 2 and 3 are not allowed. - -Bits 48-89 are as described in ITU-R 1371-4. In earlier versions to -1371-3 this was one sixbit-encoded 42-bit (7-character) string field, -the name of the AIS equipment vendor. The last 4 characters of -the string are reinterpreted as a model/serial numeric pair. It is not -clear that field practice has caught up with this incompatible change. -Implementations would be wise to decode that but span in both ways and -trust human eyes to detect when the final 4 characters of the string -or the model and serial fields are garbage. - -Interpretation of the 30 bits 132-162 in Part B is variable. If the -MMSI at 8-37 is that of an auxiliary craft, the entry is taken to -refer to a small attached auxiliary vessel and these 30 bits are read -as the MMSI of the mother ship. Otherwise the 30 bits describe vessel -dimensions as in Message Type 5. - -According to <>, an MMSI is associated with an auxiliary craft -when it is of the form 98XXXYYYY, where (1) the '98' in positions 1 -and 2 is required to designate an auxiliary craft, (2) the digits XXX -in the 3, 4 and 5 positions are the MID (the three-digit country code -as described in <>) and (3) YYYY is any decimal literal from -0000 to 9999. - -=== Type 25: Single Slot Binary Message === - -Maximum of 168 bits (a single slot). Fields after the Destination -MMSI are at variable offsets depending on that flag and the Destination -Indicator; they always occur in the same order but some may be omitted. - -//: Type 25 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description | Member |T|Units -|0-5 | 6 | Message Type | type |u|Constant: 25 -|6-7 | 2 | Repeat Indicator | repeat |u|As in CNB -|8-37 | 30 | MMSI | mmsi |u|9 digits -|38 | 1 | Destination indicator | addressed |b|0=broadcast, - 1=addressed. -|39 | 1 | Binary data flag | structured |b|See below -|40 |0/30 | Destination MMSI | dest_mmsi |u|Message destination -|? |0/16 | Application ID | app_id |u|Unsigned integer -|? |0-128 | Data | data |d|Binary data -|=============================================================================== - -If the 'addressed' flag is on, 30 bits of data at offset 40 are -interpreted as a destination MMSI. Otherwise that field span becomes -part of the message payload, with the first 16 bits used as an -Application ID if the 'structured' flag is on. - -If the 'structured' flag is on, a 16-bit application identifier is -extracted; this field is to be interpreted as a 10 bit DAC and 6-bit -FID as in message types 6 and 8. Otherwise that field span becomes -part of the message payload. - -The data fields are not, in contrast to message type 26, followed by a -radio status block. - -Note: Type 25 is extremely rare. As of April 2011 it has not been -observed even in long-duration samples from AISHub. - -=== Type 26: Multiple Slot Binary Message === - -Takes up 60-1064 bits (up to 5 slots). - -//: Type 26 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description | Member |T|Units -|0-5 | 6 | Message Type | type |u|Constant: 26 -|6-7 | 2 | Repeat Indicator | repeat |u|As in CNB -|8-37 | 30 | MMSI | mmsi |u|9 digits -|38 | 1 | Destination indicator| addressed |b|0=broadcast, - 1=addressed. -|39 | 1 | Binary data flag | structured |b|See below -|40 |0/30 | Destination MMSI | dest_mmsi |u|Message destination -|? |0/16 | Application ID | app_id |u|Unsigned integer -|? |0-1004| Data | data |d|Binary data -|? |20 | Radio status | radio |u|See <> for details. -|=============================================================================== - -The data field may span up to 5 256-bit slots in addition to the tail -end of the base slot. The application_ID field, if present, is to be -interpreted as a 10 bit DAC and 6-bit FID as in message types 6 and 8. -Documentation says the data length of each slot is 224 and adds the -note "Allows for 32 bits of bit-stuffing." - -The 20 radio status bits are always present after end-of-data in the -last slot and are in the format specified by <>. The radio -status is 20 bits rather than 19 because an extra first bit selects -whether it should be interpreted as a SOTDMA or ITDMA state. - -Note: Type 26 is extremely rare. As of April 2011 it has not been -observed even in long-duration samples from AISHub. - -=== Type 27: Long Range AIS Broadcast message === - -ITU-1371-4 says this message is primarily intended for long-range -detection of AIS Class A equipped vessels (typically by -satellite). This message has a similar content to Messages 1, 2 and 3, -but the total number of bits has been compressed to allow for -increased propagation delays associated with long-range detection - -Length according to ITU-1374 is 96 bits. However, in the wild these -are sometimes transmitted with 168 bits (a full slot). Robust decoders -should warn when this occurs but decode the first 96 bits. - -//: Type 27 -[frame="topbot",options="header"] -|============================================================================== -|Field |Len |Description |Member |u|Units -|0-5 | 6 |Message Type |type |u|Constant: 27 -|6-7 | 2 |Repeat Indicator |repeat |u|As in CNB -|8-37 | 30 |MMSI |mmsi |u|9 decimal digits -|38-38 | 1 |Position Accuracy |accuracy |u|See Common Navigation Block -|39-39 | 1 |RAIM flag |raim |u|See Common Navigation Block -|40-43 | 4 |Navigation Status |status |u|See Common Navigation Block -|44-61 | 18 |Longitude |lon |I4|minutes/10 - East positive, West negative - 181000 = N/A (default) -|62-78 | 17 |Latitude |lat |I4|minutes/10 - North positive, South negative - 91000 = N/A (default) -|79-84 | 6 |Speed Over Ground |speed |u|Knots (0-62); - 63 = N/A (default) -|85-93 | 9 |Course Over Ground |course |u|0 to 359 degrees, - 511 = not available. -|94-94 | 1 |GNSS Position status|gnss |u|0 = current GNSS position - 1 = not GNSS position (default) -|95-95 | 1 |Spare | |x|Not used -|============================================================================== - -== Local extensions == - -Some regional authorities extend the AIS message set. - -The St. Lawrence Seaway broadcasts hydrological and lock-scheduling -messages using special encodings of the binary data of message types 6 -and 8 (described in <>, freely available), and safety -information using types 12 and 14. These message types are listed -under the description of type 8. - -The U.S. Coast Guard has a system called PAWSS (Port and Water Safety -System) which uses extended AIS binary formats. <> says it's -intercompatible with the St. Lawrence Seaway system and describes three -PAWSS-specific messages in its Appendix A. - -Since 2007 the Port Authority of London has operated a Thames AIS -system covering the Thames River; it uses extensions of message types -6 and 8. It is describes in <>. - -Since 2006 there has been some effort to standardize inland-waterway -extensions, described in <>. It uses different message formats -and identifiers than the PAWS/St. Lawrence systems, which do not conform. -There is an AIS extension called "RIS" (River Information System) that -covers portions of the Danube River and Black Sea which does conform. - -<> standardizes some subtypes of messages 6 and 8 similar to -PAWSS messages for DAC 1, the international jurisdiction code. However, -in some cases identically named subtypes are assigned different FIDs. - -=== U.S. Coast Guard Extended AIVDM === - -You may occasionally see AIVDM packets with additional comma-separated -fields following the CRC-32 checksum. This is a semi-obsolescent -logging format used by the USCG, which has never documented it well -and plans to replace it with a new one based on NMEA 4.0. - -Here's a sample sentence and field breakdown: - -------------------------------------------------------------------------------- -!AIVDM,1,1,,B,15Cjtd0Oj;Jp7ilG7=UkKBoB0<06,0*63,s1234,d-119,T12.34567123,r003669958,1085889680 -------------------------------------------------------------------------------- - -Following the "*63" checksum are additional fields delimited by commas. -These fields provide additional metadata about the reception of each AIS -broadcast. - -The field beginning with the lower case "s" is a Relative Signal -Strength Indicator (RSSI) measurement from the receiver. This -measurement has a range of 0-65535. This is one of the parameters used -internally by the AIS receiver to determine the signal strength value as -reported in the field beginning with the lower case "d". This field only -exists when the AIS receiver provides this data. - -The field beginning with a lower case "d" is the signal strength -measurement for this broadcast in dBm. This field only exists when the -AIS receiver provides this data. - -The field beginning with the upper case "T" is the Time of Arrival -of the received broadcast in seconds from UTC 0. This field only exists -when the AIS receiver provides this data. - -Another optional field not shown is one that begins with an upper -case "S" and represents the slot number in which the reception occurred. -The field would appear after the checksum and before the station -identifier field. This field only exists when the AIS receiver provides -this data. Example: S0042 - -The field beginning with the lower case "r" is a station identifier -field. This field is always provided, regardless of the type of AIS -equipment. (Occasionally a base station identifier will be prefixed with -"b" instead.) - -The last field is a time tag based on the standard C programming -language time function. Both date and time to the nearest second can be -derived from this field. This field is always provided, regardless of -the type of AIS equipment. - -== NMEA Tag Blocks == - -Beginning with NMEA 4.10, the standard describes a way to intersperse -"tag blocks" with AIS sentences in order to supply additional -metadata, usually a Unix timestamp to be associated with a sentence -(or contiguous group of sentences such as an armored AIS Type 5). - -The tag block facility is complex, in some respects poorly specified, -and there has been yet much public discussion of it. This section -should be considered provisional and in need of improvement. - -The general format of a tag block is: an opening backslash, followed -by multiple comma-separated fields none of which may contain -backslashes, followed by an asterisk and NMEA checksum, followed by a -closing backslash. - -The following is an example of an AIS Type 1 sentence preceded by a -tag block: - -------------------------------------------------------------------------------------------------- -\g:1-2-73874,n:157036,s:r003669945,c:1241544035*4A\!AIVDM,1,1,,B,15N4cJ`005Jrek0H@9n`DW5608EP,0*13 -------------------------------------------------------------------------------------------------- - -Each comma-separated field is expected to be a type key, followed by a -colon, followed by content. The semantics of the type keys are as -follows (table from <>): - -Confusingly, there is a different standard introduced with NMEA 4.00, -IEC 62320-1, that uses the same tag block format but a slightly -different (overlapping) set of field keys - -.NMEA 4.00 Field Types -[frame="topbot",options="header"] -|=========================================================================== -| IEC | NMEA | Type | Description -| c | c | int>0 | UNIX time in seconds or milliseconds -| d | d | string | Destination (at most 15 chars) -| xGy | g | int-int-int | Sentence grouping -| x | n | int>0 | line count -| | r | int>0 | relative time -| s | s | string | Source / station -| i | t | string | Text string (at most 15 chars) -|=========================================================================== - -The IEC 62320-1 and NMEA 4.10 c field is an emission time for the -sentence it precedes. We're not yet sure what the time unit is. - -The NMEA 4.10 g value describes a sentence or sentence group to -associate the tag block to. It is a triple of ints separated by -dashes. The first number is the sentence number, the second is total -number of sentences to make up one group. The third number is an -identifier for that particular group. If there is no g value, the tag -block simply applies to the following sentence. - -As of May 2014 no NMEA 4.10 relative time fields have been observed in the -wild. It is unknown whether the unit is seconds or milliseconds. - -The d, i/t, and s fields are intended to be used for filtering by -station IDs included in them. - -Part of the NMEA 4.10 standard describes a configuration message facility by -which AIS message receivers can send queries to AIS senders, and under -some circumstances change the semantics if tag blocks (in particular, -by specifying time units and epoch). - -We do not yet have more definite information on the meaning of these -fields or how they are related to nearby AIVDM/AIVDO sentences. We -hope to add this in a future revision. - -== AIS Payload Byte Alignment, Padding, and Bit Stuffing == - -Warning: Here there be dragons. Read with care. Once you get through -it, you will at least not encounter anything more confusing in the -rest of this document. - -=== Byte Alignment === - -AIS is a bit-sync protocol. While some fields within AIS payloads are -8-bit-byte-aligned with preceding padding, most are not. Furthermore, -while most message variants have bit lengths that are a multiple of 8, -some do not. - -<> includes a single sentence, easy to miss, requiring -over-the-air messages to have trailing padding to a 8-bit boundary. -In most cases message lengths are a multiple of 8 with trailing spare -fields added to ensure this; thus, the requirement will not change the -transmitted bitlength of the message from what's described in the -standard. There are, however, two exceptions to this rule. - -One is an apparent error in the format design. The type 15 message -has a variant with 108 data bits and a trailing 2-bit spare field, for -110. This spare should have been 4 bits to guarantee a byte boundary -at 112 bits. Decoders need to be prepared to encounter this length -in case the transmitter has implemented the padding requirement -properly. - -The other is messages containing variable-length text packed into -6-bit nibbles: types 6, 12, and 14. They may have trailing padding -after the last nibble to get to an 8-bit boundary. Decoders should -be prepared to encounter and ignore this. - -The variable-length binary message types 8, 17, 25, and 26 are -constrained to have data payloads of a size such that the payload ends -on a byte boundary, but should not require special handling on this -account. The binary data in message types 8 and 17 is also guaranteed -to *begin* on a byte boundary, but this is not true of the addressed -variants of type 25 and 26. - -=== Interaction with AIVDM padding === - -AIVDM armoring introduces a second layer of padding, with confusing -consequences. The real payload, already padded to a bit length that -is a multiple of 8 by the AIS radio layer, gets armored as a sequence -of ASCII characters encoding 6-bit nibbles. To capture all of it, the -payload must in effect be padded to the next multiple of 6. - -Consider a type 12 message with 5 sixbit characters in it. These will -become bits 72-102 in the over-the-air message. The AIS radio layer will -pad that to 104 bits at transmission to get to an 8-bit boundary. The -receiver, reporting the data in AIVDM armoring, will pad that to 108 -bits to get to a 6-bit boundary, encode the result, and issue a pad -character of '4' to indicate that the low 4 bits of the last 6-bit -nibble should be ignored. - -Because these requirements are tricky and poorly documented in the -official standards, receivers not uncommonly get them wrong. The most -common way to get them wrong seems to be by computing the pad -character incorrectly. - -The most common error observed in the wild on AISHub is reporting a -pad 2 bits too small, making the message look like it is 2 bits longer -than it actually is. This seems for some reason to be most common -on Type 5 messages, which then decode as 426 bits rather than 424. - -Accordingly, we recommend that when validating fixed-size messages by -type and bit-length, decoders should accept messages that are up to 5 -bits over their theoretically correct length. - -For messages with a variable-length trailing payload (6, 8, 12, 14, -17, 25, 26) there is no way to detect that the pad character might -be wrong. If it is, this will manifest as truncation of the last -nibble or extra trailing zero data. - -=== Bit Stuffing === - -The following probably will not affect decoders. Nevertheless we -document it here because it is just the sort of thing that is (a) -likely to confuse implementors reading the public portions of the -standards, and (b) all too likely to become visible if there are -firmware or software errors in the transmission chain. - -There are references to "bit-stuffing" in the <> clarifications -describing certain payload fields. <> reveals the following in -3.2.2.1: "The bitstream is subject to bit stuffing. This means that if -more than 5 consecutive 1s are found in the output bit stream, a zero -is inserted. This applies to all bits except the databits of HDLC -flags." <> clarifies as follows: "On the transmitting side, -this means that if five (5) consecutive ones (1s) are found in the -output bit stream, a zero should be inserted after the five (5) -consecutive ones (1s). This applies to all bits between the HDLC flags -[...] On the receiving side, the first zero after five (5) consecutive -ones (1s) should be removed." - -It appears that this bit stuffing is meant to be performed by the AIS -radio link layer at transmission time and undone at reception time, -and should not be visible in AIVDM payloads reported by the -receiver. - -== AIS feed sites == - -Most sites that advertise "live" AIS feeds actually give you a map -display through a browser. Here are a few from which you can get raw -sentence data over a TCP/IP port for testing. Coverage on these is -not yet very comprehensive; these sites tend to have good coverage in -Europe, the U.S. and a few ports in Asia but to be spotty elsewhere. -See their siting maps for details. - -- http://aishub.net[AIS Hub]: -Share alike. You contribute a feed, you get back all feeds. - -- http://maritime.ihs.com[AIS Live]: -Subscription access to real-time data. No longer has free access even -to delayed data. - -- http://hd-sf.com:9009 -Free San Francisco Bay Area AIS feed. For non-commercial use only. - -== JSON-AIS encoding == - -Here is an application of the JSON metaformat to present AIS data in a -form more convenient for application use than AIVDM/AIVDO sentences. -This encoding is implemented by GPSD and its client libraries. It is -described here because (a) the specification is closely tied to the -field encodings, and (b) the author wishes to offer it as an -interoperability standard for other applications. - -One previous effort, <>, has been made to define a -JSON-based standard for exchange of unpacked, human-readable AIS -data. The latest version at time of writing, from December 2008,covers -only a small subset of the most common AIS messages, and many data -fields in the messages it does dump are omitted. The member names -given in the bit-field tables match the attributes used in HAM-JSON-AIS -when HAM-JSON-AIS includes that field. - -The general ground rules for JSON-AIS encoding are as follows: - -. Each sentence decodes to a JSON object. - -. When multiple kinds of JSON objects may occur in a data stream, AIS -objects have the attribute "class":"AIS". - -. Some collections of fields aggregating to a timestamp are dumped in -ISO8601 format. - -.Timestamp fields -[frame="topbot",options="header"] -|=========================================================================== -|Message| ITU/IMO fields | JSON ISO8601 | Format -| 4 | year,month,day,hour,minute,second| timestamp | %4u-%02u-%02uT%02u:%02u:%02uZ -| 5 | month,day,hour,minute | eta | %02u-%02uT%02u:%02uZ -|6(1/12)| lmonth,lday,lhour,lminute | departure | %02u-%02uT%02u:%02uZ -| | nmonth,nday,nhour,nminute | eta | %02u-%02uT%02u:%02uZ -|6(1/18)| month,day,hour,minute | arrival | %02u-%02uT%02u:%02uZ -|6(1/20)| month,day,hour,minute | arrival | %02u-%02uT%02u:%02uZ -|6(1/23)| month,day,hour,minute | timestamp | %02u-%02uT%02u:%02uZ -|6(1/28)| month,day,hour,minute | start | %02u-%02uT%02u:%02uZ -|8(1/11)| day,hour,minute | timestamp | %02uT%02u:%02uZ -|8(1/11)| day,hour,minute | timestamp | %02uT%02u:%02uZ -|8(1/13)| fmonth,fday,fhour,fminute | from | %02u-%02uT%02u:%02uZ -|8(1/13)| tmonth,tday,thour,tminute | to | %02u-%02uT%02u:%02uZ -|8(1/22)| month,day,hour,minute | timestamp | %02u-%02uT%02u:%02uZ -|8(1/27)| month,day,hour,minute | start | %02u-%02uT%02u:%02uZ -|8(200/23)| year,month,day,hour,minute | start |%4u-%02u-%02uT%02u:%02u -|8(200/23)| year,month,day,hour,minute | end |%4u-%02u-%02uT%02u:%02u -|=========================================================================== - -. There are two variants of the encoding, one scaled and one -unscaled, which differ in the treatment of float and -controlled-vocabulary fields. An AIS-JSON object may have the optional -attribute "scaled":true to signify that the rest of its fields are -scaled; if this attribute has the value 'false' or is omitted, no -scaling has been performed. Message types for which the unscaled and -scaled dumps will differ are 1-5, 9, 11, 17-19, 21-24, and 27. - -. In unscaled mode, float-valued fields are dumped in their unscaled -integer form. In scaled mode, division or other specified scaling is -applied and the value dumped as a float, *except* that certain extreme -or data-unavailable value as may be dumped as fixed strings; see the -table below. - -. Each field in the Controlled Vocabularies list in the following -table is dumped twice: once with its base name as an integer, once -with "_text" appended to the name and the vocabulary item as value. -(This behavior is new in GPSD protocol version 3.9; older versions -made integer or string display dependent on the "scaled" flag.) - -.Special fields -[frame="topbot",options="header"] -|=========================================================================== -|Message | Float Fields | Controlled Vocabularies -| 1-3 | turn, speed, lon, lat | status -| 4, 11 | lon, lat | epfd -| 5 | draught | shiptype, epfd -| 6(1/14)| lon, lat, cspeed | - -| 6(1/18)| lon, lat | - -| 6(1/20)| berth_lon, berth_lat, berth_depth | position -| 6(1/22)| lon, lat | - -| 6(1/25)| code | code* -| 6(1/28)| lon, lat | rtype -| 6(1/32)| lon, lat, cspeed | - -| 6(235/100) | - | racon, light -| 8(1/11)| lon, lat, airtemp, dewpoint, | preciptype, ice -| | visibility, waterlevel, cspeed, | -| | cspeed2, cspeed3, waveheight, | -| | swellheight, watertemp salinity | -| 8(1/17)| lon, lat | idtype* -| 8(1/18)| lon, lat | - -| 8(1/19)| - | signal, nextsignal -| 8(1/21)| lon, lat, visibility, airtemp, | - -| | watertemp, waveheight, | -| | swellheight, speed, pressure, pdelta,| -| | rwindspeed, mgustspeed, airtemp, | -| | surftemp, cloudbase, | -| | swheight1, swheight2 | -| 8(1/22)| lon, lat | - -| 8(1/25)| - | iceclass* -| 8(1/27)| lon, lat | rtype -| 8(1/31)| lon, lat, airtemp, dewpoint, | preciptype -| | visibility, waterlevel, cspeed, | -| | cspeed2, cdepth2, cspeed3, | -| | cdepth3, waveheight, | -| | swellheight, watertemp, salinity | -| 9 | lon, lat, course | - -| 17 | lon, lat | - -| 18 | lon, lat, course | - -| 19 | lon, lat, course | shiptype, epfd -| 21 | lon, lat | aid_type, epfd -| 22-23 | ne_lon,ne_lat, sw_lon, sw_lat | shiptype,stationtype -| 24 | - | shiptype -| 27 | lon, lat | - -|=========================================================================== - -This table does not include fields that are scaled by multipliers to integers. -These are reported in the multiplied form in both scaled and unscaled modes. - -Asterisked fields are not yet decoded by GPSD, but probably will be in -a future release. - -As the Beaufort scale is usually quoted numerically, conforming implementations -should do so rather than expanding to its controlled vocabulary. - -.String special values in scaled mode -[frame="topbot",options="header"] -|=========================================================================== -|Message | Fieldname | Special values -| 1-3 | turn | -"nan" = not available, "fastright" = fast right turn (above 5deg/30sec degrees), -"fastleft" = fast left turn (above 5deg/30sec degrees). -| 1-3 | speed | "nan" = not available, "fast" = speed >= 102.2 knots -| 9 | alt | "nan" = not available, "high" = alt >= 4094 meters -| 9 | speed | "nan" = not available, "fast" = speed >= 1023.0 knots -|=========================================================================== - -. Trailing arrays are dumped as JSON subobject arrays. The name of the -array item is the name given in the 'a' table entry. Explicit array count -fields (presently "waycount" in Route Info messages") are not dumped. - -. In the VTS-Generated/Synthetic Targets message, the id field is -dumped as the value of an attribute the name of which is specified by -the idtype field. - -== Open Questions == - -The AIS standards are not marvels of clear and unambiguous drafting. -We list here some open questions which could usefully be addressed -by governing authorities. - -Some of these duplicate material in paragraphs tagged with OPEN-QUESTION. -They are collected here for convenience. - -The message type summary table in <> indicates the existence -of a broadcast (unaddressed) variant of Inland Number of Persons On -Board. But no field breakdown is given for this variant. If it -supposed to be identical to the Type 6 layout, what is to be done -with the Destination MMSI field? - -Are <> time-of-day fields UTC or local? - -In <> RTA at lock/bridge/terminal message, no default is -specified for the Status field. - -In Inland Ship Static and Voyage Related Data, which of two possible -ERI numeric codesets are used for the Type field - the 4-digit codes -in the 8000-8073 range, or the AIS codes in the 1-99 range? Full ERI -codes have been observed in the wild. - -In the <> description of Message 5 extensions, footnote 6 is -incomprehensible and not actually referenced in the table. - -In the <> EMMA Warning and Signal Strength messages, the -description is not explicit about the interpretation of the longitude -and latitude fields; these semantics are assumed here from 28 and -27-bit fields in other messages. - -In the <> EMMA Warning, what are the semantics of the min and -max values? To what parameters do they apply? - -Is the <> versions of Persons On Board, which is supposed to -be Type 6 and thus addressed, erroneous? There is no destination -address field in the layout. - -<> says of the "VTS Generated/Synthetic Targets" message: -"When MMSI or IMO number is used, the least significant bit should -equal bit zero of the Target Identifier." It is unclear how "bit -zero" is to be interpreted, but it is not possible to reconcile -interpreting it as the leading bit of the field with AIS big-endian -encoding. Settling this awaits live testing. - -== References == - -[bibliography] -- [[[AIS]]] http://en.wikipedia.org/wiki/Automatic_Identification_System[Automatic -Identification System] - -- [[[SOLAS]]] - http://www.navcen.uscg.gov/enav/ais/AIS_Regs_SOLAS_MTSA_FR.pdf[SOLAS - AIS Regulations] - -- [[[US-REQUIREMENTS]]] - http://www.navcen.uscg.gov/enav/AIS/AIS_carriage_reqmts.htm[AIS - Carriage Requirements] - -- [[[ITU1371]]] - http://www.itu.int/rec/R-REC-M.1371/en - ITU Recommendation on the Technical Characteristics for a Universal - Shipborne Automatic Identification System (AIS) using Time Division - Multiple Access in the Maritime Mobile Band]. All versions are - available here. - -- [[[IALA]]] http://www.ialathree.org/iala/pages/AIS/IALATech1.5.pdf[IALA - Technical Clarifications on Recommendation ITU-R M.1371-1] - -- [[[NAVCEN]]] http://www.navcen.uscg.gov/enav/ais/[NAVCEN AIS pages] - -- [[[NMEA]]] "NMEA Revealed" This document collects information from - public sources on the proprietary NMEA 0183 standard. It is widely - distributed, but due to its hosting site having folded in late 2011, - its home location is unstable. It is probably best found by typing - the title into a search engine. - -- [[[INLAND]]] http://www.unece.org/fileadmin/DAM/trans/doc/finaldocs/sc3/ECE-TRANS-SC3-176e.pdf[International Standard for tracking and tracing on Inland Waterways] - -- [[[SEAWAY]]] http://www.greatlakes-seaway.com/en/pdf/aisdata.pdf[St. Lawrence - Seaway AIS Data Messaging Formats and Specifications] - -- [[[THAMES]]] http://www.pla.co.uk/pdfs/maritime/APPENDIX_I__II_amendment_for_2012_byelaws_FINAL.pdf[Thames AIS - Technical Requirements Specification] - -- [[[IMO236]]] http://www.imo.org/includes/blastData.asp/doc_id=4503&filename=236.pdf[IMO - Circular 236: Guidance on the Application of AIS Binary Messages (May 2004)] - -- [[[IMO289]]] - http://vislab-ccom.unh.edu/~schwehr/papers/2010-IMO-SN.1-Circ.289.pdf[IMO - 289: Guidance on the Use of AIS Application-Specific Messages - (June 2010)] - -- [[IALA-A126]] - http://www.ialathree.org/chapo/publications/documentspdf/doc_235_eng.pdf[IALA - Recommendation A-126 On The Use of the Automatic Identification System (AIS) - in Marine Aids to Navigation Services - -- [[[Schwehr]]] http://schwehr.org/blog/[Kurt Schwehr's weblog] - -- [[[IEC-PAS]]] IEC-PAS 61162-100, "Maritime navigation and - radiocommunication equipment and systems" The ASCII armoring - is described on page 26 of Annex C, Table C-1. Communicated by - Kurt Schwehr; I have not looked at it. - -- [[[IEC-62287]]] "Maritime Navigation and Radiocommunication - Equipment and Systems – Class B Shipborne Equipment of the - Automatic Identification System (AIS)" Communicated by Mike Greene; - I have not looked at it. - -- [[[ITU-MID]]] http://www.itu.int/cgi-bin/htsh/glad/cga_mids.sh?lng=E[Table - of Maritime Identification Digits] - -- [[[RAIM]]] http://en.wikipedia.org/wiki/RAIM[Receiver Autonomous - Integrity Monitoring] - -- [[[C2]]] http://www.uais.org/AISspecificationCorrigendum2.pdf[AIS - Specification Corrigendum 2] - -- [[[MMSI]]] http://www.navcen.uscg.gov/marcomms/gmdss/mmsi.htm#format[MMSI - Format] - -- [[[HAM-JSON-AIS]]] http://wiki.ham.fi/JSON_AIS.en[JSON AIS transmission protocol] - -- [[[AISHUB]]] http://www.aishub.net/[AIS Hub, the AIS data sharing center] - -- [[[PILOTPLUG]]] http://www.pilotplug.com/ - -- [[[IALA-A126]]] http://www.iala-aism.org/iala/publications/documentspdf/doc_299_eng.pdf[] - -- [[[AIS-SART]]] http://www.navcen.uscg.gov/?pageName=AISMessagesA - -- [[[SART]]] http://en.wikipedia.org/wiki/AIS-SART - -- [[[PATREON]]] https://www.patreon.com/esr - -- [[NMEA-ADVANCE]] http://www.nmea.org/Assets/0183_advancements_nmea_oct_1_2010%20(2).pdf - -== Change history == - -Version 1.0 was the initial release covering messages 1-3, 4, and 5. - -Version 1.1 adds message breakdowns for 9 and 18, explanation of the -Repeat Indicator feld, and the explanation of USCG extended AIVDM. - -Version 1.2 adds information on the ITU1371 edition 3 maneuver field, -and the RAIM flag. It also adds an important clarification about -six-bit decoding. - -Version 1.3 adds information on message types 6, 7, 12, and 13, and -attempts to demystify bit-stuffing. - -Version 1.4 adds explicit decoding tables for ASCII armoring and -six-bit ASCII. - -Version 1.5 corrects the interpretation of field 7 in AIVDM -ASCII-armored sentences. - -Version 1.6 corrects some minor errors in the interpretation of Type -5 messages. - -Version 1.7 adds descriptions for Type 10, 11, 19, 21, and 24 -messages, information about ITU-1371-3 flags in message type 18, -and the new section on Improving This Document. - -Version 1.8 fixes some broken markup and adds information about JSON-AIS. - -Version 1.9 adds more information on JSON and the member names. - -Version 1.10 fixes a typo in the formula for undoing 6-bit armoring. - -Version 1.11 describes message types 15, 16, and 17. - -Version 1.12 describes messages 20 and 22, and adds navigation aid -type codes. - -Version 1.13 documents more out-of-band values and treats radio status -blocks more uniformly. - -Version 1.14 documents message 23. - -Version 1.15 corrects an incorrect member name in message 5. It didn't -match my C code, but had no effect on conformance with the standard. I -corrected it because it confused someone working on a Python decoder. - -Version 1.16 incorporated various minor fixes and corrections from -Neal Arundale. One 'standard' fieldname changed, in message type 21: -type -> aid_type. - -Version 1.17 clarifies the role of @ as a terminator in 6-bit text. - -Version 1.18 notes a possible off-by-two error in the standards' -description of type 14, and noted that type 25 and 26 have not -been observed in the wild. It also adds a more complete description -of AIS data types and some pragmatics about spare and reserved fields. - -Version 1.19 adds a description of AIS Hub. - -Version 1.20 adds a list of AIS feed sites - just two, so far. - -Version 1.21 describes JSON-AIS more completely. It adds descriptions -for AIS messages type 25 and 26, not yet observed in the wild. - -Version 1.22 describes the problem with message length checks. -Notes on EPFD value 15 and shiptype values > 99 are added. Added -another AIS feed. Corrections and more details on message 22. - -Version 1.23 corrects some typos and numbering errors in the -description of message 19 (field widths were correct, though). -Also, AISLive no longer offers free delayed access. - -Version 1.24 breaks the Type 6 and 8 application_id field into -DAC and FID and adds tables for known DAC/FID pairs and their sources. -Unspecified fields are now omitted in JSON dumps. A new section -"AIS byte alignment, bit stuffing, and padding", reveals some -particularly black magic. - -Version 1.25 adds clarifications and more message subtypes for -U.S. Coast Guard PAWSS messages. - -Version 1.26 corrects an error in describing rate-of-turn decoding in -AIS Type 1, 2, and 3 messages, - -Version 1.27 describes the sometime U.S. practice of omitting the leading -'3' region code from MMSIs. - -Version 1.28 merges updates from IMO 289, communicated by Kurt Schwehr. - -Version 1.29 added much information on WMO special message formats in -types 6 and 8. - -Version 1.30 was revised because M.1371-4 is now a free download. -Also, we describe "pilot plugs" and AIS message type 27. We get -much more explicit about defaults in IMO236 and IMO289 messages. - -Version 1.31 shortened some C names in the Meteorological/Hydrological -messages and fixed typos. - -Version 1.32 adds descriptions of IMO Area Notice and Environmental -messages. It adds explicit type information to the tables. - -Version 1.33 notes that the home location of "NMEA Revealed" became -unstable in late 2011. - -Version 1.34 fixes a typo in the MMSI 2 field offset of message 7. - -Version 1.35 notes that 24A and 24B messages don't necessarily come -in neat adjacent pairs and that decoders need to handle this. - -Version 1.36 corrects erroneous scale factors in the IMO 289 Area -Notice and Time to Enter Port descriptions. - -Version 1.36 adds breakdowns of Aid to Navigation monitoring messages -used in the UK and the Republic of Ireland. - -Version 1.37 corrects a field signedness error in the IMO236 and -IMO289 Met/Hydro messages. - -Version 1.38 corrects a minor bug in the description of the Navigation -Message ROT field. Adds information on AIS-SART. - -Version 1.39 corrects signedness errors in the description of the Air -Temperature and Water Temperature fields in the IMO289 Weather Report -From Ship message. - -Version 1.40 notes that AIS channel codes '1' and '2' may be -encountered in the wild. - -Version 1.41 has been slightly amended because type 27s have started -showing up on satellite feeds. - -Version 1.42 fixes a typo in the Type 4 message description. - -Version 1.43 describes the ITU-R 1371-4 breakdown of the Type 24 -Vendor ID field and adds information on AIS standards for inland -waterways. Also Inland AIS standard messages are now covered. - -Version 1.44 adds substantial new information on MMSIs and updates -the <>, which was stale. - -Version 1.45 adds a description of variant AIS talker IDs and NMEA -4.10 tag blocks. - -Version 1.46 corrects an error in the specification on Inland AIS Type -10s. It also adds a bit more information on AIS tag blocks. - -Version 1.47 corrects some minor field type errors in Type 18 and Type -19 speed fields. Also corrected Type 9 radio field length. - -Version 1.48 corrects two typos in the WMO289 Area Notice and Weather -Report From Ship definitions. - -Version 1.49 adds a technical detail about non-AIS encapsulated -sentences. - -Version 1.50 fixes a couple of typos in the ISO289 Berthing Data and -Tidal Window message descriptions. - -Version 1.51 fixes an incorrect bit length in the IMO289 Hydrological -Data message. - -Version 1.52 fixes many small typos. Change Gratipay to Patreon. - -// end diff --git a/www/NMEA.adoc b/www/NMEA.adoc new file mode 100644 index 00000000..d8280075 --- /dev/null +++ b/www/NMEA.adoc @@ -0,0 +1,2622 @@ += NMEA Revealed = +:description: A programmer's guide to NMEA0183, the GPS protocol reporting standard +:keywords: NMEA0183, GPS, standard, protocol +Eric S. Raymond +v2.22, Nov 2018 + +NMEA 0183 is a proprietary protocol issued by the National Marine +Electronics Association for use in boat navigation and control +systems. Because early GPS sensors were designed for compatibility +with these systems, GPS reporting protocols are often a small +subset of NMEA 0183 or mutated from such as subset. AIS, the +Marine Automatic Identification system, also uses NMEA0183-like +packet formats. + +This document is a list of NMEA 0183 sentences with field descriptions. +It is primarily intended to help people understand GPS reports, but +also exists because the author finds life-critical protocols with +only closed/proprietary documentation deeply offensive. + +The master of this document is in asciidoc format at the GPSD project +website; you are probably seeing it as a web page. You may encounter +versions of it, in plain ASCII, that do not have a revision number and +do not list an editor. These are older and should be considered +obsolescent. + +== Sources and Applicable Standards == + +This collection may originally have been redacted from the document +cited as <>; see the list of sources at the end of this +document. The official NMEA 0183 standard was not consulted at any +point, thus this document is not a derivative work of that standard +and is not controlled by the rapacious lawyers of NMEA. + +It appears there is an international standard, IEC 61162-1, published +in 2000, that is essentially NMEA 0183. <> says it "is closely +aligned with NMEA 0183 version 2.30". Unfortunately, it costs money +and is not redistributable. + +This collection of sentences is originally from the gpsdrive +distribution, but adds more information on the following topics: + +* Old and new forms of VTG +* Units used in GGA +* Vendor extensions PRWIZCH and PMGNST +* FAA Mode Indicator field for RMC, RMB, VTG, GLL, BWC, XTE. +* New documentation on BWC, DTM, GBS, GNS, GRS, GST, MSK, and MSS sentences. +* Sentence examples merged from <> +* Sentence explanations from <> and elsewhere +* Corrected badly mangled ZDA description. +* Corrected DPT titling +* Common talker IDs +* Sentences HFB, ITS, TPC, TDS, TFI, TPC, TPR, TPT from [GLOBALSAT]. +* Sentence PASHR from <>. +* Satellite IDs: PRN vs NMEA-ID. +* Error status indications. + +== Relationship to NMEA 2000 == + +Recently the National Marine Electronics Association has attempted to +replace NMEA 0183 with a very differently structured protocol named +NMEA 2000. It is binary rather than textual, a profile or +interpretation of the Controller Area Network (CAN) protocol used in +automotive networking. Unlike NMEA 0183 it is frame-based and cannot +be transmitted over serial links. + +While newer marine electronics uses this protocol, general-purpose +GPSes have not adopted it. Thus we do not attempt to document NMEA +2000 here; see <>, <>, and <> instead. + +== NMEA version timeline == + +|======================================================================== +|NMEA 2.00 | January 1992 +|NMEA 2.01 | August 1994 +|NMEA 2.10 | October 1995 +|NMEA 2.20 | January 1997 +|NMEA 2.30 | March 1998 +|NMEA 3.00 | July 2000 +|NMEA 3.01 | January 2002 +|NMEA 4.00 | November 2008 +|NMEA 4.10 | July 2012 +|======================================================================== + +No version earlier than 2.00 is listed or archived on the NMEA website. + +The NMEA 4.00 standard states, provocatively, that it is "in theory" +backwards compatible to 2.00, and that versions before 2.00 are not +forward-compatible <>. + +== NMEA 0183 physical protocol layer == + +The NMEA specification requires a physical-level protocol compatible +with RS422 at 4800bps, 8N1 or 7N2. It is RS422 rather than RS232 +because NMEA expects many navigational devices to feed a common serial +bus. The data encoding is ASCII with the high data bit not used and +zeroed. + +Consumer-grade GPS sensors normally report over an RS232 port or a USB +port emulating an RS232 serial device; some use Bluetooth. Baud rate +is variable, with 9600 probably the most common. Most devices use +8N1; there are rare exceptions that use 7N2 (San Jose Navigation) or +even 8O1 (Trimble). + +== Sentence Mixes and NMEA Variations == + +Most GPS sensors emit only RMC, GSA, GSV, GLL, VTG, and (rarely) ZDA. +Newer ones conforming to NMEA 3.x may emit GBS as well. Other NMEA +sentences are usually only emitted by high-end maritime navigation +systems. + +The form of VTG is incompatibly variable with NMEA version. See +the detailed description of that sentence for details. + +In NMEA 2.3, several sentences (APB, BWC, BWR, GLL, RMA, RMB, RMC, +VTG, WCV, and XTE) got a new last field carrying the signal integrity +information needed by the FAA. (The values in the GGA mode field were +extended to carry this information as well.) Here are the values: + +FAA Mode Indicator + A = Autonomous mode + D = Differential Mode + E = Estimated (dead-reckoning) mode + M = Manual Input Mode + S = Simulated Mode + N = Data Not Valid + P = Precise (4.00 and later) + +This field may be empty. In pre-2.3 versions it is omitted. <> says +that according to the NMEA specification, it dominates the Status field -- +the Status field will be set to "A" (data valid) for Mode Indicators A +and D, and to "V" (data invalid) for all other values of the Mode +Indicator. This is confirmed by <>. + +In NMEA 3.0, the GBS sentence reports a complete set of error estimates. Note +however that many receivers claiming to emit "3.0" or "3.01" don't +actually ship this sentence. + +== NMEA Encoding Conventions == + +Data is transmitted in serial async, 1 start-bit, 8 data-bits, +1 stop-bit, no parity. Data-bits are in least-significant-bit +order. The standard specifies 4800 as the speed, but this is no +longer common. The most-signifacant-bit is always zero. + +An NMEA sentence consists of a start delimiter, followed by a +comma-separated sequence of fields, followed by the character '*' +(ASCII 42), the checksum and an end-of-line marker. + +The start delimiter is normally '$' (ASCII 36). Packets of AIVDM/AIVDO +data, which are otherwise formatted like NMEA, use '!'. Up to 4.00 +these are the only permitted start characters <>. + +The first field of a sentence is called the "tag" and normally +consists of a two-letter talker ID followed by a three-letter +type code. + +Where a numeric latitude or longitude is given, the two digits +immediately to the left of the decimal point are whole minutes, to the +right are decimals of minutes, and the remaining digits to the left of +the whole minutes are whole degrees. + +Eg. 4533.35 is 45 degrees and 33.35 minutes. ".35" of a minute is +exactly 21 seconds. + +Eg. 16708.033 is 167 degrees and 8.033 minutes. ".033" of a minute is +about 2 seconds. + +In NMEA 3.01 (and possibly some earlier versions), the character "^" +(HEX 5E) is reserved as an introducer for two-character hex escapes +using 0-9 and A-F, expressing an ISO 8859-1 (Latin-1) character <>. + +The Checksum is mandatory, and the last field in a sentance. It is +the 8-bit XOR of all characters in the sentance, excluding the "$", "I", +or "*" characters; but including all "," and "^". It is encoded as +two hexadecimal characters (0-9, A-F), the most-significant-nibble +being sent first. + +Sentences are terminated by a sequence. + +Maximum sentence length, including the $ and is 82 bytes. + +According to <>, the NMEA standard requires that a field (such as +altitude, latitude, or longitude) must be left empty when the GPS has +no valid data for it. However, many receivers violate this. It's +common, for example, to see latitude/longitude/altitude figures filled +with zeros when the GPS has no valid data. + +== Dates and times == + +NMEA devices report date and time in UTC, aka GMT, aka Zulu time (as +opposed to local time). But the way this report is computed results +in some odd bugs and inaccuracies. + +Date and time in GPS is represented as number of weeks from the start +of zero second of 6 January 1980, plus number of seconds into the +week. GPS time is not leap-second corrected, though satellites also +broadcast a current leap-second correction which may be updated on +three-month boundaries according to rotational bulletins issued by the +International Earth Rotation and Reference Systems Service (IERS). + +The leap-second correction is only included in the multiplexed satellite +subframe broadcast, once every 12.5 minutes. While the satellites do +notify GPSes of upcoming leap-seconds, this notification is not +necessarily processed correctly on consumer-grade devices, and may not +be available at all when a GPS receiver has just cold-booted. Thus, +reported UTC time may be slightly inaccurate between a cold boot or leap +second and the following subframe broadcast. + +GPS date and time are subject to a rollover problem in the 10-bit week +number counter, which will re-zero every 1024 weeks (roughly every 19.6 +years). The last rollover (and the first since GPS went live in 1980) +was in Aug-1999; the next will fall in Apr-2019. The new "CNAV" data +format extends the week number to 13 bits, with the first rollover +occurring in Jan-2137, but this is only used with some newly added GPS +signals, and is unlikely to be usable in most consumer-grade receivers +prior to the 2019 rollover. + +For accurate time reporting, therefore, a GPS requires a supplemental +time references sufficient to identify the current rollover period, +e.g. accurate to within 512 weeks. Many NMEA GPSes have a wired-in +assumption about the UTC time of the last rollover and will thus report +incorrect times outside the rollover period they were designed in. + +For these reasons, NMEA GPSes should not be considered high-quality +references for absolute time. Some do, however, emit pulse-per-second +RS232 signals which can be used to improve the precision of an +external clock. See <> for discussion. + +== Error status indications + +The NMEA sentences in the normal GPS inventory return four kinds of +validity flags: Mode, Status, the Active/Void bit, and in later +versions the FAA indicator mode. The FAA mode field is legally +required and orthogonal to the others. Here's how the first three used +in various sentences: + +[frame="topbot",options="header"] +|======================================================== +| | GPRMC | GPGLL | GPGGA | GPGSA +|Returns A/V | Yes | Yes | No | No +|Returns mode | No | No | No | Yes +|Returns status | No | Yes | Yes | No +|======================================================== + +The "Navigation receiver warning" is 'A' for Active and 'V' for Void. +(or warning). You will see it when either there is no satellite lock, +or to indicate a valid fix that has a DOP too high, or which fails an +elevation test. In the latter case the visible sats are below some +fixed elevation of the horizon (usually 15%, but some GPSes make this +adjustable) making position unreliable due to poor geometry and more +variable signal lag induced by lengthened atmosphere transit. + +Mode is associated with the GSA sentence associated with the last fix. +It reports whether the fix was no good, sufficient for 2D, or +sufficient for 3D (values 1, 2, and 3). + +Status will be 0 when the sample from from which the reporting +sentence was generated does not have a valid fix, 1 when it has +a valid (normal-precision) fix, and 2 when the fig is DGPS corrected +(reducing the base error). + +In addition, some sentences may use empty fields to signify invalid +data. It is not clear whether NMEA 0183 allows this, but real-world +software must cope. + +== Talker IDs == + +NMEA sentences do not identify the individual device that issued +them; the format was originally designed for shipboard multidrop +networks on which it's possible only to broadcast to all devices, not +address a specific one. + +NMEA sentences do, however, include a "talker ID" a two-character +prefix that identifies the type of the transmitting unit. By far the +most common talker ID is "GP", identifying a generic GPS, but all of +the following are well known: + +.Common talker IDs +|================================================================ +|BD | BeiDou (China) +|CD | Digital Selective Calling (DSC) +|EC | Electronic Chart Display & Information System (ECDIS) +|GA | Galileo Positioning System +|GB | BeiDou (China) +|GL | GLONASS, according to IEIC 61162-1 +|GN | Mixed GPS and GLONASS data, according to IEIC 61162-1 +|GP | Global Positioning System receiver +|II | Integrated Instrumentation +|IN | Integrated Navigation +|LC | Loran-C receiver +|QZ | QZSS regional GPS augmentation system (Japan) +|================================================================ + +EC -- ECDIS is a specialized geographical information system intended +to support professional maritime navigation. NMEA talker units +meeting the ECDIS standard use this prefix. Some of these emit GLL. + +II - II is emitted by the NMEA interfaces of several widely-used lines +of marine-navigation electronics. One is the AutoHelm system by +Raymarine; see also <> for the native protocol of these +devices. + +IN -- Some Garmin GPS units use an IN talker ID. + +CD -- Modern marine VHF radios use conventions collectively known as +Digital Selective Calling (DSC). These radios typically take data +from a local position indicating device. This data is used in +conjunction with a unique (FCC assigned) ID to cause your radio to +broadcast your position data to others. Conversely, these radios are +capable of recieving position data of other stations and emitting +sentences indicating other station positions. This lets you plot the +position of other vessels on a chart, for instance. There has been at +least one instance of a DSC enabled radio overloading (mis-using) the +LC talker prefix for this purpose. Otherwise they use the CD prefix. +A vessel's nav system is likely to have both CD and some other +position indicating talker on its bus(es). + +LC - Loran-C is a marine navigation system run by the U.S. government, +which is planning to shut it down in favor of GPS. Some non-Loran +devices emit GLL but use this talker ID for backward-compatibility +reasons, so it may outlast the actual Loran system. + +Until the U.S. Coast Guard terminated the Omega Navigation System in +1997, another common talker prefix was "OM" for an Omega Navigation +System receiver. + +Here is a more complete list of talker ID prefixes. Most are not +relevant to GPS systems. + +Note that talker IDs made obsolete by newer revisions of the +standards may still be emitted by older devices. Support +for them may be present in the GPSD project. + +.Big list of talker IDs +|================================================================ +|AB | Independent AIS Base Station +|AD | Dependent AIS Base Station +|AG | Autopilot - General +|AP | Autopilot - Magnetic +|BN | Bridge navigational watch alarm system +|CC | Computer - Programmed Calculator (obsolete) +|CD | Communications - Digital Selective Calling (DSC) +|CM | Computer - Memory Data (obsolete) +|CS | Communications - Satellite +|CT | Communications - Radio-Telephone (MF/HF) +|CV | Communications - Radio-Telephone (VHF) +|CX | Communications - Scanning Receiver +|DE | DECCA Navigation (obsolete) +|DF | Direction Finder +|DM | Velocity Sensor, Speed Log, Water, Magnetic +|DU | Duplex repeater station +|EC | Electronic Chart Display & Information System (ECDIS) +|EP | Emergency Position Indicating Beacon (EPIRB) +|ER | Engine Room Monitoring Systems +|GP | Global Positioning System (GPS) +|HC | Heading - Magnetic Compass +|HE | Heading - North Seeking Gyro +|HN | Heading - Non North Seeking Gyro +|II | Integrated Instrumentation +|IN | Integrated Navigation +|LA | Loran A (obsolete) +|LC | Loran C (obsolete) +|MP | Microwave Positioning System (obsolete) +|NL | Navigation light controller +|OM | OMEGA Navigation System (obsolete) +|OS | Distress Alarm System (obsolete) +|RA | RADAR and/or ARPA +|SD | Sounder, Depth +|SN | Electronic Positioning System, other/general +|SS | Sounder, Scanning +|TI | Turn Rate Indicator +|TR | TRANSIT Navigation System +|U# | '#' is a digit 0 ... 9; User Configured +|UP | Microprocessor controller +|VD | Velocity Sensor, Doppler, other/general +|VW | Velocity Sensor, Speed Log, Water, Mechanical +|WI | Weather Instruments +|YC | Transducer - Temperature (obsolete) +|YD | Transducer - Displacement, Angular or Linear (obsolete) +|YF | Transducer - Frequency (obsolete) +|YL | Transducer - Level (obsolete) +|YP | Transducer - Pressure (obsolete) +|YR | Transducer - Flow Rate (obsolete) +|YT | Transducer - Tachometer (obsolete) +|YV | Transducer - Volume (obsolete) +|YX | Transducer +|ZA | Timekeeper - Atomic Clock +|ZC | Timekeeper - Chronometer +|ZQ | Timekeeper - Quartz +|ZV | Timekeeper - Radio Update, WWV or WWVH +|================================================================ + +== Satellite IDs == + +Satellites may be identified by one of two different numbers in +sentences such as GSV: a PRN number associated with their radio code, +or an NMEA-ID. + +For satellites 1-32, the GPS constellation, these numbers are the +same. For satellites associated with WAAS (Wide Area Augmentation +System), EGNOS (European Geostationary Navigation Overlay Service), +and MSAS (Multi-functional Satellite Augmentation System), they are +different. + +Here is a table of NMEA-ID allocations above 32 as of March 2010: + +[frame="topbot",options="header"] +|==================================================== +|System |Satellite |PRN |NMEA-ID +|EGNOS |AOR-E |120 |33 +|EGNOS |Artemis |124 |37 +|EGNOS |IOR-W |126 |39 +|MSAS |MTSAT-1 |129 |42 +|EGNOS |IOR-E |131 |44 +|WAAS |AMR |133 |46 +|WAAS |PanAm |135 |48 +|MSAS |MTSAT-2 |137 |50 +|WAAS |Anik |138 |51 +|==================================================== + +In general, NMEA-ID = PRN - 87. Theoretically, all NMEA-emitting +devices should emit NMEA-IDs. In practice, some pass through PRNs. + +Documentation on IDs for GLONASS satellites is scanty. +The manual for one GLONASS-capable receiver has this to say: + +To avoid possible confusion caused by repetition of satellite ID +numbers when using multiple satellite systems, the following +convention has been adopted: + +a. GPS satellites are identified by their PRN numbers, which range from 1 to 32. + +b. The numbers 33-64 are reserved for WAAS satellites. The WAAS system +PRN numbers are 120-138. The offset from NMEA WAAS SV ID to WAAS PRN +number is 87. A WAAS PRN number of 120 minus 87 yields the SV ID of 33. +The addition of 87 to the SV ID yields the WAAS PRN number. + +c. The numbers 65-96 are reserved for GLONASS satellites. GLONASS +satellites are identified by 64+satellite slot number. The slot +numbers are 1 through 24 for the full constellation of 24 satellites, +this gives a range of 65 through 88. The numbers 89 through 96 are +available if slot numbers above 24 are allocated to on-orbit spares. + +Other sources such as <> confirm that the NMEA standard +assigns NMEA IDs 65-96 to GLONASS. The following +table is our best guess of NMEA usage in 2018: + +[frame="topbot",options="header"] +|==================================================== +| 1 - 32 | GPS +| 33 - 54 | Various SBAS systems (EGNOS, WAAS, SDCM, GAGAN, MSAS) +| 55 - 64 | not used (might be assigned to further SBAS systems) +| 65 - 88 | GLONASS +| 89 - 96 | GLONASS (future extensions?) +| 97 - 119 | not used +| 120 - 151 | not used (SBAS PRNs occupy this range) +| 152 - 158 | Various SBAS systems (EGNOS, WAAS, SDCM, GAGAN, MSAS) +| 159 - 172 | not used +| 173 - 182 | IMES +| 193 - 197 | QZSS +| 196 - 200 | QZSS (future extensions?) +| 201 - 235 | BeiDou (u-blox, not NMEA) +| 301 - 336 | GALILEO +| 401 - 437 | BeiDou (NMEA) +|==================================================== + +GLONASS satellite numbers come in two flavors. If a sentence +has a GL talker ID, expect the skyviews to be GLONASS-only and +in the range 1-32; you must add 64 to get a globally-unique +NMEA ID. If the sentence has a GN talker ID, the device emits +a multi-constellation skyview with GLONASS IDs aleady in +the 65-96 range. + +QZSS is a geosynchronous (*not geostationary*) system of three +(possibly four) satellites in highly eliptical, inclined, +orbits. It is designed to provide coverage in Japan's +urban canyons. + +BeiDou-1 consists of 4 geostationary satellites operated by China, +operational since 2004. Coverage area is the Chinese mainland. +gpsd does not support this, as this requires special hardware, +and prior arrangements with the operator, who calculates and +returns the position fix. + +BeiDou-2 (earlier known as COMPASS) is a system of 35 satellites, +including 5 geostationary for compatability with BeiDou-1. +As of late 2015, coverage is complete over most of Asia and the +West Pacific. It is expected to be fully operational by 2020, by +when coverage area is expected to be worldwide. + +Note that the PRN system is becoming increasingly fragmented and +unworkable. New GPS denote each satellite, and their signals, by their +constellation (gnssID), satellite id in that constellation (svId), and +signal type (sigId). NMEA, as of version 4, has not adapted. + +== Obsolete sentences == + +Note that sentances made obsolete by newer revisions of the +standards may still be emitted by devices. +Support for them may be present in the GPSD project. + +The following NMEA sentences have been designated "obsolete" in a +publicly available NMEA document dated 2009. + +|================================================================ +|APA | Autopilot Sentence "A" +|BER | Bearing & Distance to Waypoint, Dead Reckoning, Rhumb Line +|BPI | Bearing & Distance to Point of Interest +|DBK | Depth Below Keel +|DBS | Depth Below Surface +| +|DRU | Dual Doppler Auxiliary Data +|GDA | Dead Reckoning Positions +|GLA | Loran-C Positions +|GOA | OMEGA Positions +|GXA | TRANSIT Positions +|GTD | Geographical Position, Loran-C TDs +|GXA | TRANSIT Position +|HCC | Compass Heading +|HCD | Heading and Deviation +|HDM | Heading, Magnetic +|HDT | Heading, True +|HVD | Magnetic Variation, Automatic +|HVM | Magnetic Variation, Manually Set +|IMA | Vessel Identification +|MDA | Meteorological Composite +|MHU | Humidity +|MMB | Barometer +|MTA | Air Temperature +|MWH | Wave Height +|MWS | Wind & Sea State +| +|Rnn | Routes +|SBK | Loran-C Blink Status +|SCY | oran-C Cycle Lock Status +|SCD | Loran-C ECDs +|SDB | Loran-C Signal Strength +|SGD | Position Accuracy Estimate +|SGR | Loran-C Chain Identifier +|SIU | Loran-C Stations in Use +|SLC | Loran-C Status +|SNC | Navigation Calculation Basis +|SNU | Loran-C SNR Status +|SPS | Loran-C Predicted Signal Strength +|SSF | Position Correction Offset +|STC | Time Constant +|STR | Tracking Reference +|SYS | Hybrid System Configuration +|================================================================ + +== NMEA-Standard Sentences == + +Here are the NMEA-standard sentences we know about: + +=== AAM - Waypoint Arrival Alarm === + +This sentence is generated by some units to indicate the status of +arrival (entering the arrival circle, or passing the perpendicular of +the course line) at the destination waypoint. + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 + | | | | | | + $--AAM,A,A,x.x,N,c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Status, BOOLEAN, A = Arrival circle entered, V = not passed +2. Status, BOOLEAN, A = perpendicular passed at waypoint, V = not passed +3. Arrival circle radius +4. Units of radius, nautical miles +5. Waypoint ID +6. Checksum + +Example: GPAAM,A,A,0.10,N,WPTNME*43 + +WPTNME is the waypoint name. + +=== ALM - GPS Almanac Data === + +This sentence expresses orbital data for a specified GPS satellite. + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + | | | | | | | | | | | | | | | | + $--ALM,x.x,x.x,xx,x.x,hh,hhhh,hh,hhhh,hhhh,hhhhhh,hhhhhh,hhhhhh,hhhhhh,hhh,hhh,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Total number of messages +2. Message Number +3. Satellite PRN number (01 to 32) +4. GPS Week Number +5. SV health, bits 17-24 of each almanac page +6. Eccentricity +7. Almanac Reference Time +8. Inclination Angle +9. Rate of Right Ascension +10. Root of semi-major axis +11. Argument of perigee +12. Longitude of ascension node +13. Mean anomaly +14. F0 Clock Parameter +15. F1 Clock Parameter +16. Checksum + +Fields 5 through 15 are dumped as raw hex. + +Example: + +$GPALM,1,1,15,1159,00,441d,4e,16be,fd5e,a10c9f,4a2da4,686e81,58cbe1,0a4,001*5B + +=== APA - Autopilot Sentence "A" === + +This sentence is sent by some GPS receivers to allow them to be used +to control an autopilot unit. This sentence is commonly used by +autopilots and contains navigation receiver warning flag status, +cross-track-error, waypoint arrival status, initial bearing from +origin waypoint to the destination, continuous bearing from present +position to destination and recommended heading-to-steer to +destination waypoint for the active navigation leg of the journey. + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 11 + | | | | | | | | | | | + $--APA,A,A,x.xx,L,N,A,A,xxx,M,c---c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Status + V = Loran-C Blink or SNR warning + V = general warning flag or other navigation systems when a reliable + fix is not available +2. Status + V = Loran-C Cycle Lock warning flag + A = OK or not used +3. Cross Track Error Magnitude +4. Direction to steer, L or R +5. Cross Track Units (Nautic miles or kilometers) +6. Status + A = Arrival Circle Entered +7. Status + A = Perpendicular passed at waypoint +8. Bearing origin to destination +9. M = Magnetic, T = True +10. Destination Waypoint ID +11. checksum + +Example: $GPAPA,A,A,0.10,R,N,V,V,011,M,DEST,011,M*82 + +=== APB - Autopilot Sentence "B" === + +This is a fixed form of the APA sentence with some ambiguities removed. + +Note: Some autopilots, Robertson in particular, misinterpret "bearing +from origin to destination" as "bearing from present position to +destination". This is likely due to the difference between the APB +sentence and the APA sentence. for the APA sentence this would be the +correct thing to do for the data in the same field. APA only differs +from APB in this one field and APA leaves off the last two fields +where this distinction is clearly spelled out. This will result in +poor performance if the boat is sufficiently off-course that the two +bearings are different. + 13 15 +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 11 12| 14| + | | | | | | | | | | | | | | | + $--APB,A,A,x.x,a,N,A,A,x.x,a,c--c,x.x,a,x.x,a*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Status + V = Loran-C Blink or SNR warning + V = general warning flag or other navigation systems when a reliable + fix is not available +2. Status + V = Loran-C Cycle Lock warning flag + A = OK or not used +3. Cross Track Error Magnitude +4. Direction to steer, L or R +5. Cross Track Units, N = Nautical Miles +6. Status + A = Arrival Circle Entered +7. Status + A = Perpendicular passed at waypoint +8. Bearing origin to destination +9. M = Magnetic, T = True +10. Destination Waypoint ID +11. Bearing, present position to Destination +12. M = Magnetic, T = True +13. Heading to steer to destination waypoint +14. M = Magnetic, T = True +15. Checksum + +Example: $GPAPB,A,A,0.10,R,N,V,V,011,M,DEST,011,M,011,M*82 + +=== BOD - Bearing - Waypoint to Waypoint === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--BOD,x.x,T,x.x,M,c--c,c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Bearing Degrees, TRUE +2. T = True +3. Bearing Degrees, Magnetic +4. M = Magnetic +5. TO Waypoint +6. FROM Waypoint +7. Checksum + +Example 1: $GPBOD,099.3,T,105.6,M,POINTB,*01 + +Waypoint ID: "POINTB" Bearing 99.3 True, 105.6 Magnetic This sentence +is transmitted in the GOTO mode, without an active route on your +GPS. WARNING: this is the bearing from the moment you press enter in +the GOTO page to the destination waypoint and is NOT updated +dynamically! To update the information, (current bearing to waypoint), +you will have to press enter in the GOTO page again. + +Example 2: $GPBOD,097.0,T,103.2,M,POINTB,POINTA*52 + +This sentence is transmitted when a route is active. It contains the +active leg information: origin waypoint "POINTA" and destination +waypoint "POINTB", bearing between the two points 97.0 True, 103.2 +Magnetic. It does NOT display the bearing from current location to +destination waypoint! WARNING Again this information does not change +until you are on the next leg of the route. (The bearing from POINTA +to POINTB does not change during the time you are on this leg.) + +This sentence has been replaced by BWW in NMEA 4.00 (and posssibly +earlier versions) <>. + +=== BWC - Bearing & Distance to Waypoint - Great Circle === + +------------------------------------------------------------------------------ + 12 + 1 2 3 4 5 6 7 8 9 10 11| 13 14 + | | | | | | | | | | | | | | + $--BWC,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x.x,T,x.x,M,x.x,N,c--c,m,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. UTCTime +2. Waypoint Latitude +3. N = North, S = South +4. Waypoint Longitude +5. E = East, W = West +6. Bearing, True +7. T = True +8. Bearing, Magnetic +9. M = Magnetic +10. Nautical Miles +11. N = Nautical Miles +12. Waypoint ID +13. FAA mode indicator (NMEA 2.3 and later, optional) +14. Checksum + +Example 1: $GPBWC,081837,,,,,,T,,M,,N,*13 + +Example 2: GPBWC,220516,5130.02,N,00046.34,W,213.8,T,218.0,M,0004.6,N,EGLM*11 + +=== BWR - Bearing and Distance to Waypoint - Rhumb Line === + +------------------------------------------------------------------------------ + 11 + 1 2 3 4 5 6 7 8 9 10 | 12 13 + | | | | | | | | | | | | | + $--BWR,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x.x,T,x.x,M,x.x,N,c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. UTCTime +2. Waypoint Latitude +3. N = North, S = South +4. Waypoint Longitude +5. E = East, W = West +6. Bearing, True +7. T = True +8. Bearing, Magnetic +9. M = Magnetic +10. Nautical Miles +11. N = Nautical Miles +12. Waypoint ID +13. Checksum + +=== BWW - Bearing - Waypoint to Waypoint === + +Bearing calculated at the FROM waypoint. + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--BWW,x.x,T,x.x,M,c--c,c--c*hh +------------------------------------------------------------------------------ + + Field Number: +1. Bearing Degrees, TRUE +2. T = True +3. Bearing Degrees, Magnetic +4. M = Magnetic +5. TO Waypoint +6. FROM Waypoint +7. Checksum + +=== DBK - Depth Below Keel === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--DBK,x.x,f,x.x,M,x.x,F*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Depth, feet +2. f = feet +3. Depth, meters +4. M = meters +5. Depth, Fathoms +6. F = Fathoms +7. Checksum + +=== DBS - Depth Below Surface === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--DBS,x.x,f,x.x,M,x.x,F*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Depth, feet +2. f = feet +3. Depth, meters +4. M = meters +5. Depth, Fathoms +6. F = Fathoms +7. Checksum + +=== DBT - Depth below transducer === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--DBT,x.x,f,x.x,M,x.x,F*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Depth, feet +2. f = feet +3. Depth, meters +4. M = meters +5. Depth, Fathoms +6. F = Fathoms +7. Checksum + +In real-world sensors, sometimes not all three conversions are reported. +So you might see something like $SDDBT,,f,22.5,M,,F*cs + +Example: $SDDBT,7.8,f,2.4,M,1.3,F*0D + +=== DCN - Decca Position === + +------------------------------------------------------------------------------ + 11 13 16 + 1 2 3 4 5 6 7 8 9 10| 12| 14 15| 17 + | | | | | | | | | | | | | | | | | + $--DCN,xx,cc,x.x,A,cc,x.x,A,cc,x.x,A,A,A,A,x.x,N,x*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Decca chain identifier +2. Red Zone Identifier +3. Red Line Of Position +4. Red Master Line Status +5. Green Zone Identifier +6. Green Line Of Position +7. Green Master Line Status +8. Purple Zone Identifier +9. Purple Line Of Position +10. Purple Master Line Status +11. Red Line Navigation Use +12. Green Line Navigation Use +13. Purple Line Navigation Use +14. Position Uncertainity +15. N = Nautical Miles +16. Fix Data Basis + - 1 = Normal Pattern + - 2 = Lane Identification Pattern + - 3 = Lane Identification Transmissions +17. Checksum + +(The DCN sentence is obsolete as of 3.01) + +=== DPT - Depth of Water === + +------------------------------------------------------------------------------ + 1 2 3 + | | | + $--DPT,x.x,x.x*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Depth, meters +2. Offset from transducer, + positive means distance from tansducer to water line + negative means distance from transducer to keel +3. Checksum + +This sentence was incorrectly titled "Heading - Deviation & Variation" +in <>. It's documented at + + +Example: $INDPT,2.3,0.0*46 + +=== DTM - Datum Reference === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 + | | | | | | | | | + $ --DTM,ref,x,llll,c,llll,c,aaa,ref*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Local datum code. +2. Local datum subcode. May be blank. +3. Latitude offset (minutes) +4. N or S +5. Longitude offset (minutes) +6. E or W +7. Altitude offset in meters +8. Datum name. What's usually seen here is "W84", the standard + WGS84 datum used by GPS. +9. Checksum. + +Example: $GPDTM,W84,C*52 + +=== FSI - Frequency Set Information === + +Set (or report) frequency, mode of operation and transmitter power level of a +radiotelephone. + +------------------------------------------------------------------------------ + 1 2 3 4 5 + | | | | | + $--FSI,xxxxxx,xxxxxx,c,x*hh +------------------------------------------------------------------------------ + + Field Number: +1. Transmitting Frequency +2. Receiving Frequency +3. Communications Mode (NMEA Syntax 2) +4. Power Level +5. Checksum + +=== GBS - GPS Satellite Fault Detection === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 + | | | | | | | | | + $--GBS,hhmmss.ss,x.x,x.x,x.x,x.x,x.x,x.x,x.x*hh +------------------------------------------------------------------------------ + +Field Number: + +1. UTC time of the GGA or GNS fix associated with this sentence +2. Expected error in latitude (meters) +3. Expected error in longitude (meters) +4. Expected error in altitude (meters) +5. PRN of most likely failed satellite +6. Probability of missed detection for most likely failed satellite +7. Estimate of bias in meters on most likely failed satellite +8. Standard deviation of bias estimate +9. Checksum + +Note: Source <> describes a proprietary extension of GBS with +a 9th data field. The 8-field version is in NMEA 3.0. + +Example: $GPGBS,125027,23.43,M,13.91,M,34.01,M*07 + +=== GGA - Global Positioning System Fix Data === + +This is one of the sentences commonly emitted by GPS units. + +Time, Position and fix related data for a GPS receiver. + +------------------------------------------------------------------------------ + 11 + 1 2 3 4 5 6 7 8 9 10 | 12 13 14 15 + | | | | | | | | | | | | | | | + $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Universal Time Coordinated (UTC) +2. Latitude +3. N or S (North or South) +4. Longitude +5. E or W (East or West) +6. GPS Quality Indicator, + - 0 - fix not available, + - 1 - GPS fix, + - 2 - Differential GPS fix + (values above 2 are 2.3 features) + - 3 = PPS fix + - 4 = Real Time Kinematic + - 5 = Float RTK + - 6 = estimated (dead reckoning) + - 7 = Manual input mode + - 8 = Simulation mode +7. Number of satellites in view, 00 - 12 +8. Horizontal Dilution of precision (meters) +9. Antenna Altitude above/below mean-sea-level (geoid) (in meters) +10. Units of antenna altitude, meters +11. Geoidal separation, the difference between the WGS-84 earth + ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level + below ellipsoid +12. Units of geoidal separation, meters +13. Age of differential GPS data, time in seconds since last SC104 + type 1 or 9 update, null field when DGPS is not used +14. Differential reference station ID, 0000-1023 +15. Checksum + +Example: + +$GNGGA,001043.00,4404.14036,N,12118.85961,W,1,12,0.98,1113.0,M,-21.3,M,,*47 + +=== GLC - Geographic Position, Loran-C === + +This sentence is obsolete over most of its former coverage area. The +US/Canadian/Russian Loran-C network was shut down in 2010; it is still +as of 2015 in limited use in Europe. Loran-C operations in Norway +will cease from 1st Jan 2016. <> + +------------------------------------------------------------------------------ + 12 14 + 1 2 3 4 5 6 7 8 9 10 11| 13| + | | | | | | | | | | | | | | + $--GLC,xxxx,x.x,a,x.x,a,x.x,a.x,x,a,x.x,a,x.x,a*hh +------------------------------------------------------------------------------ + +Field Number: + +1. GRI Microseconds/10 +2. Master TOA Microseconds +3. Master TOA Signal Status +4. Time Difference 1 Microseconds +5. Time Difference 1 Signal Status +6. Time Difference 2 Microseconds +7. Time Difference 2 Signal Status +8. Time Difference 3 Microseconds +9. Time Difference 3 Signal Status +10. Time Difference 4 Microseconds +11. Time Difference 4 Signal Status +12. Time Difference 5 Microseconds +13. Time Difference 5 Signal Status +14. Checksum + +=== GLL - Geographic Position - Latitude/Longitude === + +This is one of the sentences commonly emitted by GPS units. + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 + | | | | | | | | + $--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,a,m,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Latitude +2. N or S (North or South) +3. Longitude +4. E or W (East or West) +5. Universal Time Coordinated (UTC) +6. Status A - Data Valid, V - Data Invalid +7. FAA mode indicator (NMEA 2.3 and later) +8. Checksum + +Example: $GNGLL,4404.14012,N,12118.85993,W,001037.00,A,A*67 + +=== GNS - Fix data === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 11 12 13 + | | | | | | | | | | | | | +$--GNS,hhmmss.ss,llll.ll,a,yyyyy.yy,a,c--c,xx,x.x,x.x,x.x,x.x,x.x*hh +------------------------------------------------------------------------------ + +Field Number: + +1. UTC +2. Latitude +3. N or S (North or South) +4. Longitude +5. E or W (East or West) +6. Mode indicator (non-null) +7. Total number of satelites in use,00-99 +8. HDROP +9. Antenna altitude, meters, re:mean-sea-level(geoid. +10. Goeidal separation meters +11. Age of diferential data +12. Differential reference station ID +13. Checksum + +The Mode indicator is two or more characters, with the first and second +defined for GPS and GLONASS. Further characters may be defined. For +each system, the character can have a value (table may be incomplete): + +* N = Constellation not in use, or no valid fix +* A = Autonomous (non-differential) +* D = Differential mode +* P = Precise (no degradation, like Selective Availability) +* R = Real Time Kinematic +* F = Float RTK +* E = Estimated (dead reckoning) Mode +* M = Manual Input Mode +* S = Simulator Mode + +Example: $GPGNS,112257.00,3844.24011,N,00908.43828,W,AN,03,10.5,,,,*57 + +=== GRS - GPS Range Residuals === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + | | | | | | | | | | | | | | | + $ --GRS,hhmmss.ss,m,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. TC time of associated GGA fix +2. 0 = Residuals used in GGA, 1 = residuals calculated after GGA +3. Satellite 1 residual in meters +4. Satellite 2 residual in meters +5. Satellite 3 residual in meters +6. Satellite 4 residual in meters (blank if unused) +7. Satellite 5 residual in meters (blank if unused) +8. Satellite 6 residual in meters (blank if unused) +9. Satellite 7 residual in meters (blank if unused) +10. Satellite 8 residual in meters (blank if unused) +11. Satellite 9 residual in meters (blank if unused) +12. Satellite 10 residual in meters (blank if unused) +13. Satellite 11 residual in meters (blank if unused) +14. Satellite 12 residual in meters (blank if unused) +15. Checksum + +The order of satellites MUST match those in the last GSA. + +Example: $GPGRS,024603.00,1,-1.8,-2.7,0.3,,,,,,,,,*6C + +Note that the talker ID may be GP, GL, or GN, depending on if the residuals +are for GPS-only, GLONASS-only, or combined solution, respectively. + +=== GST - GPS Pseudorange Noise Statistics === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 + | | | | | | | | | + $ --GST,hhmmss.ss,x,x,x,x,x,x,x,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. TC time of associated GGA fix +2. Total RMS standard deviation of ranges inputs to the navigation solution +3. Standard deviation (meters) of semi-major axis of error ellipse +4. Standard deviation (meters) of semi-minor axis of error ellipse +5. Orientation of semi-major axis of error ellipse (true north degrees) +6. Standard deviation (meters) of latitude error +7. Standard deviation (meters) of longitude error +8. Standard deviation (meters) of altitude error +9. Checksum + +Example: $GPGST,182141.000,15.5,15.3,7.2,21.8,0.9,0.5,0.8*54 + + +=== GSA - GPS DOP and active satellites === + +This is one of the sentences commonly emitted by GPS units. + +------------------------------------------------------------------------------ + 1 2 3 14 15 16 17 18 + | | | | | | | | + $--GSA,a,a,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x.x,x.x,x.x*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Selection mode: M=Manual, forced to operate in 2D or 3D, A=Automatic, 3D/2D +2. Mode (1 = no fix, 2 = 2D fix, 3 = 3D fix) +3. ID of 1st satellite used for fix +4. ID of 2nd satellite used for fix +5. ID of 3rd satellite used for fix +6. ID of 4th satellite used for fix +7. ID of 5th satellite used for fix +8. ID of 6th satellite used for fix +9. ID of 7th satellite used for fix +10. ID of 8th satellite used for fix +11. ID of 9th satellite used for fix +12. ID of 10th satellite used for fix +13. ID of 11th satellite used for fix +14. ID of 12th satellite used for fix +15. PDOP +16. HDOP +17. VDOP +18. Checksum + +Example: $GNGSA,A,3,80,71,73,79,69,,,,,,,,1.83,1.09,1.47*17 + +=== GSV - Satellites in view === + +This is one of the sentences commonly emitted by GPS units. + +These sentences describe the sky position of a UPS satellite in view. +Typically they're shipped in a group of 2 or 3. + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 n + | | | | | | | | + $--GSV,x,x,x,x,x,x,x,...*hh +------------------------------------------------------------------------------ + +Field Number: + +1. total number of GSV messages to be transmitted in this group +2. 1-origin number of this GSV message within current group +3. total number of satellites in view (leading zeros sent) +4. satellite PRN number (leading zeros sent) +5. elevation in degrees (-90 to 90) (leading zeros sent) +6. azimuth in degrees to true north (000 to 359) (leading zeros sent) +7. SNR in dB (00-99) (leading zeros sent) + more satellite info quadruples like 4-7 + n) checksum + +Example: + $GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74 + $GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74 + $GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D + +Some GPS receivers may emit more than 12 quadruples (more than three +GPGSV sentences), even though NMEA-0813 doesn't allow this. (The +extras might be WAAS satellites, for example.) Receivers may also +report quads for satellites they aren't tracking, in which case the +SNR field will be null; we don't know whether this is formally allowed +or not. + +Example: $GLGSV,3,3,09,88,07,028,*51 + +=== GTD - Geographic Location in Time Differences === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 + | | | | | | + $--GTD,x.x,x.x,x.x,x.x,x.x*hh +------------------------------------------------------------------------------ + +Field Number: + +1. time difference +2. time difference +3. time difference +4. time difference +5. time difference + n) checksum + + +=== GXA - TRANSIT Position - Latitude/Longitude === + +Location and time of TRANSIT fix at waypoint + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 + | | | | | | | | + $--GXA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,c--c,X*hh +------------------------------------------------------------------------------ + +Field Number: + +1. UTC of position fix +2. Latitude +3. East or West +4. Longitude +5. North or South +6. Waypoint ID +7. Satelite number +8. Checksum + +(The GXA sentence is obsolete as of 3.01.) + +=== HDG - Heading - Deviation & Variation === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 + | | | | | | + $--HDG,x.x,x.x,a,x.x,a*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Magnetic Sensor heading in degrees +2. Magnetic Deviation, degrees +3. Magnetic Deviation direction, E = Easterly, W = Westerly +4. Magnetic Variation degrees +5. Magnetic Variation direction, E = Easterly, W = Westerly +6. Checksum + +=== HDM - Heading - Magnetic === + +Vessel heading in degrees with respect to magnetic north produced by +any device or system producing magnetic heading. + +------------------------------------------------------------------------------ + 1 2 3 + | | | + $--HDM,x.x,M*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Heading Degrees, magnetic +2. M = magnetic +3. Checksum + +=== HDT - Heading - True === + +Actual vessel heading in degrees true produced by any device or system +producing true heading. + +------------------------------------------------------------------------------ + 1 2 3 + | | | + $--HDT,x.x,T*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Heading Degrees, true +2. T = True +3. Checksum + +Example: $GPHDT,274.07,T*03 + +=== HFB - Trawl Headrope to Footrope and Bottom === + +------------------------------------------------------------------------------ + 1 2 3 4 5 + | | | | | + $--HFB,x.x,M,y.y,M*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Distance from headrope to footrope +2. Meters (0-100) +3. Distance from headrope to bottom +4. Meters (0-100) +5. Checksum + +From <>. Shown with a "@II" leader rather than "$GP". + +=== HSC - Heading Steering Command === + +------------------------------------------------------------------------------ + 1 2 3 4 5 + | | | | | + $--HSC,x.x,T,x.x,M,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Heading Degrees, True +2. T = True +3. Heading Degrees, Magnetic +4. M = Magnetic +5. Checksum + +<> describes a completely different meaning for this +sentence, having to do with water temperature sensors. It is +unclear which is correct. + +=== ITS - Trawl Door Spread 2 Distance === + +------------------------------------------------------------------------------ + 1 2 3 + | | | + $--ITS,x.x,M*hh +------------------------------------------------------------------------------ + +Field Number) + +1. Second spread distance +2. Meters +3. Checksum. + +From <>. Shown with a "@II" leader rather than "$GP". + +=== LCD - Loran-C Signal Data === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + | | | | | | | | | | | | | | + $--LCD,xxxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx*hh +------------------------------------------------------------------------------ + +Field Number: + +1. GRI Microseconds/10 +2. Master Relative SNR +3. Master Relative ECD +4. Time Difference 1 Microseconds +5. Time Difference 1 Signal Status +6. Time Difference 2 Microseconds +7. Time Difference 2 Signal Status +8. Time Difference 3 Microseconds +9. Time Difference 3 Signal Status +10. Time Difference 4 Microseconds +11. Time Difference 4 Signal Status +12. Time Difference 5 Microseconds +13. Time Difference 5 Signal Status +14. Checksum + +=== MDA - Meteorilogical Composite === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + | | | | | | | | | | | | | | | | | | | | | + $--MDA,n.nn,I,n.nnn,B,n.n,C,n.C,n.n,n,n.n,C,n.n,T,n.n,M,n.n,N,n.n,M*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Barometric pressure, inches of mercury, to the nearest 0.01 inch +2. I = inches of mercury +3. Barometric pressure, bars, to the nearest .001 bar +4. B = bars +5. Air temperature, degrees C, to the nearest 0.1 degree C +6. C = degrees C +7. Water temperature, degrees C (this field left blank by WeatherStation) +8. C = degrees C +9. Relative humidity, percent, to the nearest 0.1 percent +10. Absolute humidity, percent +11. Dew point, degrees C, to the nearest 0.1 degree C +12. C = degrees C +13. Wind direction, degrees True, to the nearest 0.1 degree +14. T = true +15. Wind direction, degrees Magnetic, to the nearest 0.1 degree +16. M = magnetic +17. Wind speed, knots, to the nearest 0.1 knot +18. N = knots +19. Wind speed, meters per second, to the nearest 0.1 m/s +20. M = meters per second +21. Checksum + +Obsolete as of 2009. + +=== MSK - Control for a Beacon Receiver === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 + | | | | | | + $--MSK,nnn,m,nnn,m,nnn*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Frequency to use +2. Frequency mode, A=auto, M=manual +3. Beacon bit rate +4. Bitrate, A=auto, M=manual +5. Frequency for MSS message status (null for no status) +6. Checksum + +=== MSS - Beacon Receiver Status === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 + | | | | | | + $--MSS,nn,nn,fff,bbb,xxx*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Signal strength (dB 1uV) +2. Signal to noise ratio (dB) +3. Beacon frequency (kHz) +4. Beacon data rate (BPS) +5. Unknown integer value +6. Checksum + +Example: $GPMSS,0,0,0.000000,200,*5A + +=== MTW - Mean Temperature of Water === + +------------------------------------------------------------------------------ + 1 2 3 + | | | + $--MTW,x.x,C*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Degrees +2. Unit of Measurement, Celcius +3. Checksum + +<> lists this as "Meteorological Temperature of Water", which +is probably incorrect. + +Example: $INMTW,17.9,C*1B + +=== MWV - Wind Speed and Angle === + +------------------------------------------------------------------------------ + 1 2 3 4 5 + | | | | | + $--MWV,x.x,a,x.x,a*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Wind Angle, 0 to 360 degrees +2. Reference, R = Relative, T = True +3. Wind Speed +4. Wind Speed Units, K/M/N +5. Status, A = Data Valid +6. Checksum + +=== OLN - Omega Lane Numbers === + +------------------------------------------------------------------------------ + 1 2 3 4 + |--------+ |--------+ |--------+ | + $--OLN,aa,xxx,xxx,aa,xxx,xxx,aa,xxx,xxx*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Omega Pair 1 +2. Omega Pair 1 +3. Omega Pair 1 +4. Checksum + +(The OLN sentence is obsolete as of 2.30) + +=== OSD - Own Ship Data === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 + | | | | | | | | | | + $--OSD,x.x,A,x.x,a,x.x,a,x.x,x.x,a*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Heading, degrees true +2. Status, A = Data Valid +3. Vessel Course, degrees True +4. Course Reference +5. Vessel Speed +6. Speed Reference +7. Vessel Set, degrees True +8. Vessel drift (speed) +9. Speed Units +10. Checksum + +=== R00 - Waypoints in active route === + +------------------------------------------------------------------------------ + 1 n + | | + $--R00,c---c,c---c,....*hh +------------------------------------------------------------------------------ + +Field Number: + +1. waypoint ID + +... + +n) checksum + +=== RMA - Recommended Minimum Navigation Information === + +------------------------------------------------------------------------------ + 12 + 1 2 3 4 5 6 7 8 9 10 11| + | | | | | | | | | | | | + $--RMA,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,x.x,x.x,x.x,a*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Blink Warning +2. Latitude +3. N or S +4. Longitude +5. E or W +6. Time Difference A, uS +7. Time Difference B, uS +8. Speed Over Ground, Knots +9. Track Made Good, degrees true +10. Magnetic Variation, degrees +11. E or W +12. Checksum + +=== RMB - Recommended Minimum Navigation Information === + +To be sent by a navigation receiver when a destination waypoint is active. + +------------------------------------------------------------------------------ + 14 + 1 2 3 4 5 6 7 8 9 10 11 12 13| 15 + | | | | | | | | | | | | | | | + $--RMB,A,x.x,a,c--c,c--c,llll.ll,a,yyyyy.yy,a,x.x,x.x,x.x,A,m,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Status, A= Active, V = Void +2. Cross Track error - nautical miles +3. Direction to Steer, Left or Right +4. TO Waypoint ID +5. FROM Waypoint ID +6. Destination Waypoint Latitude +7. N or S +8. Destination Waypoint Longitude +9. E or W +10. Range to destination in nautical miles +11. Bearing to destination in degrees True +12. Destination closing velocity in knots +13. Arrival Status, A = Arrival Circle Entered +14. FAA mode indicator (NMEA 2.3 and later) +15. Checksum + +Example: $GPRMB,A,0.66,L,003,004,4917.24,N,12309.57,W,001.3,052.5,000.5,V*0B + +=== RMC - Recommended Minimum Navigation Information === + +This is one of the sentences commonly emitted by GPS units. + +------------------------------------------------------------------------------ + 12 + 1 2 3 4 5 6 7 8 9 10 11| 13 + | | | | | | | | | | | | | + $--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a,m,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. UTC Time +2. Status, V=Navigation receiver warning A=Valid +3. Latitude +4. N or S +5. Longitude +6. E or W +7. Speed over ground, knots +8. Track made good, degrees true +9. Date, ddmmyy +10. Magnetic Variation, degrees +11. E or W +12. FAA mode indicator (NMEA 2.3 and later) +13. Checksum + +A status of V means the GPS has a valid fix that is below an internal +quality threshold, e.g. because the dilution of precision is too high +or an elevation mask test failed. + +Example: $GNRMC,001031.00,A,4404.13993,N,12118.86023,W,0.146,,100117,,,A*7B + +=== ROT - Rate Of Turn === + +------------------------------------------------------------------------------ + 1 2 3 + | | | + $--ROT,x.x,A*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Rate Of Turn, degrees per minute, "-" means bow turns to port +2. Status, A means data is valid +3. Checksum + +Example: $HEROT,0.0,A*2B + +=== RPM - Revolutions === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 + | | | | | | + $--RPM,a,x,x.x,x.x,A*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Sourse, S = Shaft, E = Engine +2. Engine or shaft number +3. Speed, Revolutions per minute +4. Propeller pitch, % of maximum, "-" means astern +5. Status, A means data is valid +6. Checksum + + +=== RSA - Rudder Sensor Angle === + +------------------------------------------------------------------------------ + 1 2 3 4 5 + | | | | | + $--RSA,x.x,A,x.x,A*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Starboard (or single) rudder sensor, "-" means Turn To Port +2. Status, A means data is valid +3. Port rudder sensor +4. Status, A means data is valid +5. Checksum + +=== RSD - RADAR System Data === + +------------------------------------------------------------------------------ + 14 + 1 2 3 4 5 6 7 8 9 10 11 12 13| + | | | | | | | | | | | | | | + $--RSD,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,a,a*hh +------------------------------------------------------------------------------ + +(Some fields are missing from this description.) + +Field Number: +1. Unknown +2. Unknown +3. Unknown +4. Unknown +5. Unknown +6. Unknown +7. Unknown +8. Unknown +9. Cursor Range From Own Ship +10. Cursor Bearing Degrees Clockwise From Zero +11. Range Scale +12. Range Units +13 Unknown +14. Checksum + +=== RTE - Routes === + +------------------------------------------------------------------------------ + 1 2 3 4 5 x n + | | | | | | | + $--RTE,x.x,x.x,a,c--c,c--c, ..... c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Total number of messages being transmitted +2. Message Number +3. Message mode + c = complete route, all waypoints + w = working route, the waypoint you just left, the waypoint + you're heading to, then all the rest +4. Waypoint ID + +More waypoints follow. Last field is a checksum as usual. + +The Garmin 65 and possibly other units report a $GPR00 in the same format. + +Example: $GPRTE,1,1,c,0*07 + +=== SFI - Scanning Frequency Information === + +------------------------------------------------------------------------------ + 1 2 3 4 x + | | | | | + $--SFI,x.x,x.x,xxxxxx,c .......... xxxxxx,c*hh +------------------------------------------------------------------------------ + +Field Number: +1. Total Number Of Messages +2. Message Number +3. Frequency 1 +4. Mode 1 +x. Checksum + +=== STN - Multiple Data ID === + +This sentence is transmitted before each individual sentence where +there is a need for the Listener to determine the exact source of data +in the system. Examples might include dual-frequency depthsounding +equipment or equipment that integrates data from a number of sources +and produces a single output. + +------------------------------------------------------------------------------ + 1 2 + | | + $--STN,x.x,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Talker ID Number +2. Checksum + +=== TDS - Trawl Door Spread Distance === + +------------------------------------------------------------------------------ + 1 2 3 + | | | + $--TDS,x.x,M*hh +------------------------------------------------------------------------------ + +Field Number) + +1. Distance between trawl doors +2. Meters (0-300) +3. Checksum. + +From <>. Shown with a "@II" leader rather than "$GP". + +=== TFI - Trawl Filling Indicator === + +------------------------------------------------------------------------------ + 1 2 3 4 + | | | | + $--TFI,x,y,z*hh +------------------------------------------------------------------------------ + +Field number: + +1. Catch sensor #1 (0 = off, 1 = on, 2 = no answer) +2. Catch sensor #2 (0 = off, 1 = on, 2 = no answer) +3. Catch sensor #3 (0 = off, 1 = on, 2 = no answer) + +From <>. Shown with a "@II" leader rather than "$GP". + +=== TPC - Trawl Position Cartesian Coordinates === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--TPC,x,M,y,P,z.z,M*hh, +------------------------------------------------------------------------------ + +Field Number: + +1. Horizontal distance from the vessel center line +2. Meters +3. Horizontal distance from the transducer to the trawl along the + vessel center line. The value is normally positive assuming the + trawl is located behind the vessel. +4. Meters +5. Depth of the trawl below the surface +6. Meters +7. Checksum + +From <>. Shown with a "@II" leader rather than "$GP". +This entry actually merges their TPC description with another +entry labeled (apparently incorrectly) TPT, which differs from the +TPT shown below. + +=== TPR - Trawl Position Relative Vessel === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--TPR,x,M,y,P,z.z,M*hh, +------------------------------------------------------------------------------ + +Field Number: + +1. Horizontal range relative to target +2. Meters (0-4000) +3. Bearing to target relative to vessel heading. Resolution is one degree. +4. Separator +5. Depth of trawl below the surface +6. Meters (0-2000) +7. Checksum + +From <>. Shown with a "@II" leader rather than "$GP". + +=== TPT - Trawl Position True === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--TPT,x,M,y,P,z.z,M*hh, +------------------------------------------------------------------------------ + +Field Number: + +1. Horizontal range relative to target +2. Meters (0-4000) +3. True bearing to taget (ie. relative north). Resolution is one degree. +4. Separator +5. Depth of trawl below the surface +6. Meters (0-2000) +7. Checksum + +From <>. Shown with a "@II" leader rather than "$GP". + +=== TRF - TRANSIT Fix Data === + +------------------------------------------------------------------------------ + 13 + 1 2 3 4 5 6 7 8 9 10 11 12| + | | | | | | | | | | | | | + $--TRF,hhmmss.ss,xxxxxx,llll.ll,a,yyyyy.yy,a,x.x,x.x,x.x,x.x,xxx,A*hh +------------------------------------------------------------------------------ + +Field Number: + +1. UTC Time +2. Date, ddmmyy +3. Latitude +4. N or S +5. Longitude +6. E or W +7. Elevation Angle +8. Number of iterations +9. Number of Doppler intervals +10. Update distance, nautical miles +11. Satellite ID +12. Data Validity +13. Checksum + +(The TRF sentence is obsolete as of 2.3.0) + +=== TTM - Tracked Target Message === + +------------------------------------------------------------------------------ + 11 13 + 1 2 3 4 5 6 7 8 9 10| 12| 14 + | | | | | | | | | | | | | | + $--TTM,xx,x.x,x.x,a,x.x,x.x,a,x.x,x.x,a,c--c,a,a*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Target Number (0-99) +2. Target Distance +3. Bearing from own ship +4. Bearing Units +5. Target Speed +6. Target Course +7. Course Units +8. Distance of closest-point-of-approach +9. Time until closest-point-of-approach "-" means increasing +10. "-" means increasing +11. Target name +12. Target Status +13. Reference Target +14. Checksum + +<> gives this in a slightly different form, with 14th and +15th fields conveying time of observation and whether target +acquisition was automatic or manual. + +=== VBW - Dual Ground/Water Speed === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--VBW,x.x,x.x,A,x.x,x.x,A*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Longitudinal water speed, "-" means astern +2. Transverse water speed, "-" means port +3. Status, A = Data Valid +4. Longitudinal ground speed, "-" means astern +5. Transverse ground speed, "-" means port +6. Status, A = Data Valid +7. Checksum + +=== VDR - Set and Drift === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--VDR,x.x,T,x.x,M,x.x,N*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Degress True +2. T = True +3. Degrees Magnetic +4. M = Magnetic +5. Knots (speed of current) +6. N = Knots +7. Checksum + +=== VHW - Water speed and heading === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 + | | | | | | | | | + $--VHW,x.x,T,x.x,M,x.x,N,x.x,K*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Degress True +2. T = True +3. Degrees Magnetic +4. M = Magnetic +5. Knots (speed of vessel relative to the water) +6. N = Knots +7. Kilometers (speed of vessel relative to the water) +8. K = Kilometers +9. Checksum + +<> describes a different format in which the first three +fields are water-temperature measurements. It's not clear which +is correct. + +=== VLW - Distance Traveled through Water === + +------------------------------------------------------------------------------ + 1 2 3 4 5 + | | | | | + $--VLW,x.x,N,x.x,N*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Total cumulative distance +2. N = Nautical Miles +3. Distance since Reset +4. N = Nautical Miles +5. Checksum + +=== VPW - Speed - Measured Parallel to Wind === + +------------------------------------------------------------------------------ + 1 2 3 4 5 + | | | | | + $--VPW,x.x,N,x.x,M*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Speed, "-" means downwind +2. N = Knots +3. Speed, "-" means downwind +4. M = Meters per second +5. Checksum + +=== VTG - Track made good and Ground speed === + +This is one of the sentences commonly emitted by GPS units. + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 + | | | | | | | | | | + $--VTG,x.x,T,x.x,M,x.x,N,x.x,K,m,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Track Degrees +2. T = True +3. Track Degrees +4. M = Magnetic +5. Speed Knots +6. N = Knots +7. Speed Kilometers Per Hour +8. K = Kilometers Per Hour +9. FAA mode indicator (NMEA 2.3 and later) +10. Checksum + +Note: in some older versions of NMEA 0183, the sentence looks like this: + +------------------------------------------------------------------------------ + 1 2 3 4 5 + | | | | | + $--VTG,x.x,x,x.x,x.x,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. True course over ground (degrees) 000 to 359 +2. Magnetic course over ground 000 to 359 +3. Speed over ground (knots) 00.0 to 99.9 +4. Speed over ground (kilometers) 00.0 to 99.9 +5. Checksum + +The two forms can be distinguished by field 2, which will be +the fixed text 'T' in the newer form. The new form appears +to have been introduced with NMEA 3.01 in 2002. + +Some devices, such as those described in <>, leave the +magnetic-bearing fields 3 and 4 empty. + +Example: $GPVTG,220.86,T,,M,2.550,N,4.724,K,A*34 + +=== VWR - Relative Wind Speed and Angle === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 + | | | | | | | | | + $--VWR,x.x,a,x.x,N,x.x,M,x.x,K*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Wind direction magnitude in degrees +2. Wind direction Left/Right of bow +3. Speed +4. N = Knots +5. Speed +6. M = Meters Per Second +7. Speed +8. K = Kilometers Per Hour +9. Checksum + +=== WCV - Waypoint Closure Velocity === + +------------------------------------------------------------------------------ + 1 2 3 4 + | | | | + $--WCV,x.x,N,c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Velocity +2. N = knots +3. Waypoint ID +4. Checksum + +=== WNC - Distance - Waypoint to Waypoint === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--WNC,x.x,N,x.x,K,c--c,c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Distance, Nautical Miles +2. N = Nautical Miles +3. Distance, Kilometers +4. K = Kilometers +5. TO Waypoint +6. FROM Waypoint +7. Checksum + +=== WPL - Waypoint Location === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 + | | | | | | + $--WPL,llll.ll,a,yyyyy.yy,a,c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Latitude +2. N or S (North or South) +3. Longitude +4. E or W (East or West) +5. Waypoint name +6. Checksum + +=== XDR - Transducer Measurement === + +------------------------------------------------------------------------------ + 1 2 3 4 n + | | | | | + $--XDR,a,x.x,a,c--c, ..... *hh +------------------------------------------------------------------------------ + +Field Number: + +1. Transducer Type +2. Measurement Data +3. Units of measurement +4. Name of transducer + +There may be any number of quadruplets like this, each describing a +sensor. The last field will be a checksum as usual. + +Example: + +$HCXDR,A,171,D,PITCH,A,-37,D,ROLL,G,367,,MAGX,G,2420,,MAGY,G,-8984,,MAGZ*41 + +=== XTE - Cross-Track Error, Measured === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--XTE,A,A,x.x,a,N,m,*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Status + - V = Loran-C Blink or SNR warning + - V = general warning flag or other navigation systems when a reliable + fix is not available +2. Status + - V = Loran-C Cycle Lock warning flag + - A = OK or not used +3. Cross Track Error Magnitude +4. Direction to steer, L or R +5. Cross Track Units, N = Nautical Miles +6. FAA mode indicator (NMEA 2.3 and later, optional) +7. Checksum + +Example: $GPXTE,V,V,,,N,S*43 + +=== XTR - Cross Track Error - Dead Reckoning === + +------------------------------------------------------------------------------ + 1 2 3 4 + | | | | + $--XTR,x.x,a,N*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Magnitude of cross track error +2. Direction to steer, L or R +3. Units, N = Nautical Miles +4. Checksum + +=== ZDA - Time & Date - UTC, day, month, year and local time zone === + +This is one of the sentences commonly emitted by GPS units. + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $--ZDA,hhmmss.ss,xx,xx,xxxx,xx,xx*hh +------------------------------------------------------------------------------ + +Field Number: + +1. UTC time (hours, minutes, seconds, may have fractional subsecond) +2. Day, 01 to 31 +3. Month, 01 to 12 +4. Year (4 digits) +5. Local zone description, 00 to +- 13 hours +6. Local zone minutes description, apply same sign as local hours +7. Checksum + +Example: $GPZDA,160012.71,11,03,2004,-1,00*7D + +=== ZFO - UTC & Time from origin Waypoint === + +------------------------------------------------------------------------------ + 1 2 3 4 + | | | | + $--ZFO,hhmmss.ss,hhmmss.ss,c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Universal Time Coordinated (UTC) +2. Elapsed Time +3. Origin Waypoint ID +4. Checksum + +=== ZTG - UTC & Time to Destination Waypoint === + +------------------------------------------------------------------------------ + 1 2 3 4 + | | | | + $--ZTG,hhmmss.ss,hhmmss.ss,c--c*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Universal Time Coordinated (UTC) +2. Time Remaining +3. Destination Waypoint ID +4. Checksum + +=== Other sentences === + +There is evidence for the existence of the following NMEA sentences +on the Web: + +|====================================================== +|ACK - Alarm Acknowldgement +|ADS - Automatic Device Status +|AKD - Acknowledge Detail Alarm Condition +|ALA - Set Detail Alarm Condition +|ASD - Autopilot System Data +|BEC - Bearing & Distance to Waypoint - Dead Reckoning +|CEK - Configure Encryption Key Command +|COP - Configure the Operational Period, Command +|CUR - Water Current Layer +|DCR - Device Capability Report +|DDC - Display Dimming Control +|DOR - Door Status Detection +|DSC - Digital Selective Calling Information +|DSE - Extended DSC +|DSI - DSC Transponder Initiate +|DSR - DSC Transponder Response +|ETL - Engine Telegraph Operation Status +|EVE - General Event Message +|FIR - Fire Detection +|MWD - Wind Direction & Speed +|TLL - Target Latitude and Longitude +|WDR - Distance to Waypoint - Rhumb Line +|WDC - Distance to Waypoint - Great Circle +|ZDL - Time and Distance to Variable Point +|====================================================== + +$CDDSC is described in <>. + +== Vendor extensions == + +This list is very incomplete. + +=== PASHR - RT300 proprietary roll and pitch sentence === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 9 10 11 12 + | | | | | | | | | | | | +$PASHR,hhmmss.sss,hhh.hh,T,rrr.rr,ppp.pp,xxx.xx,a.aaa,b.bbb,c.ccc,d,e*hh +------------------------------------------------------------------------------ + +Field number: + +1. hhmmss.sss - UTC time +2. hhh.hh - Heading in degrees +3. T - flag to indicate that the Heading is True Heading (i.e. to True North) +4. rrr.rr - Roll Angle in degrees +5. ppp.pp - Pitch Angle in degrees +6. xxx.xx - Heave +7. a.aaa - Roll Angle Accuracy Estimate (Stdev) in degrees +8. b.bbb - Pitch Angle Accuracy Estimate (Stdev) in degrees +9. c.ccc - Heading Angle Accuracy Estimate (Stdev) in degrees +10. d - Aiding Status +11. e - IMU Status +12. hh - Checksum + +<> describes this sentence as NMEA, though other sources say it +is Ashtech proprietary and describe a different format. + +Example: + +$PASHR,085335.000,224.19,T,-01.26,+00.83,+00.00,0.101,0.113,0.267,1,0*06 + +=== PGRME - Garmin Estimated Error === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 + | | | | | | | + $PGRME,hhh,M,vvv,M,ttt,M*hh +------------------------------------------------------------------------------ + +Field Number: + +1. Estimated horizontal position error (HPE), +2. M=meters +3. Estimated vertical position error (VPE) +4. M=meters +5. Overall spherical equivalent position error +6. M=meters +7. Checksum + +Example: $PGRME,15.0,M,45.0,M,25.0,M*22 + +=== PMGNST - Magellan Status === + +------------------------------------------------------------------------------ + 1 2 3 4 5 6 7 8 + | | | | | | | | + $PMGNST,xx.xx,m,t,nnn,xx.xx,nnn,nn,c +------------------------------------------------------------------------------ + +Field Number: + +1. Firmware version number? +2. Mode (1 = no fix, 2 = 2D fix, 3 = 3D fix) +3. T if we have a fix +4. numbers change - unknown +5. time left on the GPS battery in hours +6. numbers change (freq. compensation?) +7. PRN number receiving current focus +8. nmea_checksum + +Only supported on Magellan GPSes. + +=== PRWIZCH - Rockwell Channel Status === + +------------------------------------------------------------------------------ + $PRWIZCH,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,c*hh +------------------------------------------------------------------------------ + +Fields consist of 12 pairs of a satellite PRN followed by a +signal quality number in the range 0-7 (0 worst, 7 best). + +Only emitted by the now-obsolete Zodiac (Rockwell) chipset. + +=== PUBX 00 - u-blox Lat/Long Position Data === + +------------------------------------------------------------------------------ + $PUBX,00,hhmmss.ss,Latitude,N,Longitude,E,AltRef,NavStat,Hacc,Vacc,SOG,COG,Vvel,+ageC,HDOP,VDOP,TDOP,GU,RU,DR,*hh +------------------------------------------------------------------------------ + +Example: + +$PUBX,00,081350.00,4717.113210,N,00833.915187,E,546.589,G3,2.1,2.0,0.007,77.52,0+.007,,0.92,1.19,0.77,9,0,0*5F + +Only emitted by u-blox Antaris chipset. + +=== PUBX 01 - u-blox UTM Position Data === + +The $PUBX,01 is a UTM (Universal Transverse Mercator projection) version +of the $PUBX,00 sentence. + +------------------------------------------------------------------------------ +$PUBX,01,hhmmss.ss,Easting,E,Northing,N,AltMSL,NavStat,Hacc,Vacc,SOG,COG,Vvel,ag+eC,HDOP,VDOP,TDOP,GU,RU,DR,*hh +------------------------------------------------------------------------------ + +Example: + +$PUBX,01,075142.00,467125.245,E,5236949.763,N,498.235,G3,2.1,1.9,0.005,85.63,0.0+00,,0.78,0.90,0.52,12,0,0*65 + +Only emitted by u-blox Antaris chipset. + +=== PUBX 03 - u-blox Satellite Status === + +------------------------------------------------------------------------------ + $PUBX,03,GT{,ID,s,AZM,EL,SN,LK},*hh +------------------------------------------------------------------------------ + +Example: + +$PUBX,03,11,23,-,,,45,010,29,-,,,46,013,07,-,,,42,015,08,U,067,31,42,025,10,U,19+5,33,46,026,18,U,326,08,39,026,17,-,,,32,015,26,U,306,66,48,025,27,U,073,10,36,+026,28,U,089,61,46,024,15,-,,,39,014*0D + +Only emitted by u-blox Antaris chipset. + +(There's no PUBX 02) + +=== PUBX 04 - u-blox Time of Day and Clock Information === + +------------------------------------------------------------------------------ +$PUBX,04,hhmmss.ss,ddmmyy,UTC_TOW,week,reserved,Clk_B,Clk_D,PG,*hh +------------------------------------------------------------------------------ + +Example: + +$PUBX,04,073731.00,091202,113851.00,1196,113851.00,1930035,-2660.664,43,*3C<+LF> + +Only emitted by u-blox Antaris chipset. + +=== TMVTD - Transas VTS / SML tracking system report === + +------------------------------------------------------------------------------ +$TMVTD,DDMMYY,hhmmss.ss,a,xxxx,c—c,llll.llll,a,yyyyy.yyyy,a,x.x,a,x.x,a,a*hh +------------------------------------------------------------------------------ + +‘TM’ indicates message generated by SML tracking system. ‘VTD’ is +name of the message. + +Field Number: + +1. Day/month/year (two-digit year, unknown base century) +2. Hour/minute/second to 0.1 sec precion, UTC. +3. ‘R’ indicates that this is an update for a radar track. No other + values are valid +4. Internal unique ID number. Can’t be changed even when target is + re-identified +5. Target alias. Can be changed when the target identification data is + edited. Symbols “$”, “*” “,” and “.” are not allowed to be used + within the alias word. This field is variable length, at most 21v + characters. +6. Latitude in degrees (two leading digits) and decimal minutes + (trailing digits). +7. N or S for North or South latitude. +8. Longitude in degrees (three leading digits) and decimal minutes + (trailing digits). +9. E or W for East or West longitude. +10. Target course in decimal degrees. +11. Fixed to T, indicates true course. +12. Target speed in decimal knots. +13. Fixed to N, indicates decimal speed in knots. +14. T or D. T = tracked, D = dropped. Message with status + “dropped” is sent only once after target is dropped. +15. NMEA checksum. + +Transas is a mnanufacturer of proprietary ECDIS systems. + +Described in <>, actually a Maltese government document. + +== References == + +[bibliography] +- [[[BETKE]]] + "The NMEA 0183 protocol" + http://www.scribd.com/mcocco/d/6365285-The-NMEA-0183-Protocol + Probably the ancestor of this document. Compiled by Klaus Betke + and dated May 2000 with a revision in 2001. + +- [[[CANBUS]]] + "Wikipedia: CAN bus" + http://en.wikipedia.org/wiki/CAN_bus + +- [[[NMEA2000]]] + "Wikipedia: NMEA 2000" + http://en.wikipedia.org/wiki/NMEA_2000 + +- [[[KEVERSOFT]]] + http://www.keversoft.com/downloads/packetlogger_20120305_explain.txt + +- [[[DEPRIEST]]] + "NMEA data" + http://www.gpsinformation.org/dale/nmea.htm + Used for PMGNST and the FAA mode code. + +- [[[MX521]]] + "MX521 GPS/DGPS Sensor Installation Manual" + http://www.mx-marine.com/downloads/MX521_Install_manual_051804.pdf + Used for GBS, GRS. + +- [[[MX535]]] + "MX535 UAIS Ship Borne Class A Transponder Unit Techical & Installation Manual" + http://www.mx-marine.com/downloads/mx535/MX535_Tech_Manual_Rev_E.pdf + Used for GNS. + +- [[[ZODIAC]]] + "Zodiac Serial Data Interface Specification" + http://users.rcn.com/mardor/serial.pdf + Used for PRWIZCH. + +- [[[GH79L4N]]] + "Specifications for GPS Receiver GH-79L4-N" + http://www.tecsys.de/db/gps/gh79l1an_intant.pdf + Used for GPDTM. + +- [[[GIDS]]] + "GPS - NMEA sentence information" + http://aprs.gids.nl/nmea/ + Used for BWC, MSK, MSS. + +- [[[NMEAFAQ]]] + "The NMEA FAQ" + http://vancouver-webpages.com/peter/nmeafaq.txt + Used for R00. + +- [[[UNMEA]]] + "Understanding NMEA 0183" + http://pcptpp030.psychologie.uni-regensburg.de/trafficresearch/NMEA0183/ + Source for the claim that NMEA requires undefined data fields to + be empty. + +- [[[NTUM]]] + "NemaTalker User Manual" + http://www.sailsoft.nl/NemaTalker/UserManual/InstrGPS.htm + Source for the claim that Mode Indicator dominates Status. + +- [[[IEC61162-1]]] + "International Standard IEC 61162-1" (preview) + http://domino.iec.ch/preview/info_iec61162-1%7Bed2.0%7Den.pdf + +- [[[SEATALK]]] + "SeaTalk Technical Reference" + http://www.thomasknauf.de/seatalk.htm + +- [[[SATSTAT]]] "NMEA IDs" https://github.com/mvglasow/satstat/wiki/NMEA-IDs + +- [[[GLOBALSAT]]] + "NMEA (National Marine Electronics Association) 0183 Protocol" + http://www.usglobalsat.com/faq_details/NMEA.htm + +- [[[PASHR]]] + "News - NMEA PASHR Output Format Added" + http://www.oxts.com/default.asp?pageRef=76&newsID=69 + +- [[[WAAS]]] + "WAAS Information" + http://gpsinformation.net/exe/waas.html + +- [[[PPS]]] + "Pulse per second" + http://en.wikipedia.org/wiki/Pulse_per_second + +- [[[MALTESE]]] + "Procurement of a Fixed-Wing Maritime Patrol Aircraft" + https://secure2.gov.mt/eprocurement/Tenders/file.ashx?f=9832DB05E65C774258580284031EC72CC315D954A7108B5E. + +- [[NMEA-ADVANCE]] + "NMEA 0183 Advancements" (describes 'P' value of FAA mode) + http://www.nmea.org/Assets/0183_advancements_nmea_oct_1_2010%20(2).pdf + +- [[CDDSC]] + "Data Interface in Digital Selective Calling Class-D Radios" + http://continuouswave.com/whaler/reference/DSC_Datagrams.html + +- [[ANON]] + Anonymous commentator(s) are persons who have volunteered information + about the NMEA standard(s) but do not wish to be identified. + +- [[[NORWAY]]] + "Etterretninger for sjøfarende" Notoces for Mariners, see p26 + http://kartverket.no/efs-documents/editions/2015/efs01-2015.pdf diff --git a/www/NMEA.txt b/www/NMEA.txt deleted file mode 100644 index d8280075..00000000 --- a/www/NMEA.txt +++ /dev/null @@ -1,2622 +0,0 @@ -= NMEA Revealed = -:description: A programmer's guide to NMEA0183, the GPS protocol reporting standard -:keywords: NMEA0183, GPS, standard, protocol -Eric S. Raymond -v2.22, Nov 2018 - -NMEA 0183 is a proprietary protocol issued by the National Marine -Electronics Association for use in boat navigation and control -systems. Because early GPS sensors were designed for compatibility -with these systems, GPS reporting protocols are often a small -subset of NMEA 0183 or mutated from such as subset. AIS, the -Marine Automatic Identification system, also uses NMEA0183-like -packet formats. - -This document is a list of NMEA 0183 sentences with field descriptions. -It is primarily intended to help people understand GPS reports, but -also exists because the author finds life-critical protocols with -only closed/proprietary documentation deeply offensive. - -The master of this document is in asciidoc format at the GPSD project -website; you are probably seeing it as a web page. You may encounter -versions of it, in plain ASCII, that do not have a revision number and -do not list an editor. These are older and should be considered -obsolescent. - -== Sources and Applicable Standards == - -This collection may originally have been redacted from the document -cited as <>; see the list of sources at the end of this -document. The official NMEA 0183 standard was not consulted at any -point, thus this document is not a derivative work of that standard -and is not controlled by the rapacious lawyers of NMEA. - -It appears there is an international standard, IEC 61162-1, published -in 2000, that is essentially NMEA 0183. <> says it "is closely -aligned with NMEA 0183 version 2.30". Unfortunately, it costs money -and is not redistributable. - -This collection of sentences is originally from the gpsdrive -distribution, but adds more information on the following topics: - -* Old and new forms of VTG -* Units used in GGA -* Vendor extensions PRWIZCH and PMGNST -* FAA Mode Indicator field for RMC, RMB, VTG, GLL, BWC, XTE. -* New documentation on BWC, DTM, GBS, GNS, GRS, GST, MSK, and MSS sentences. -* Sentence examples merged from <> -* Sentence explanations from <> and elsewhere -* Corrected badly mangled ZDA description. -* Corrected DPT titling -* Common talker IDs -* Sentences HFB, ITS, TPC, TDS, TFI, TPC, TPR, TPT from [GLOBALSAT]. -* Sentence PASHR from <>. -* Satellite IDs: PRN vs NMEA-ID. -* Error status indications. - -== Relationship to NMEA 2000 == - -Recently the National Marine Electronics Association has attempted to -replace NMEA 0183 with a very differently structured protocol named -NMEA 2000. It is binary rather than textual, a profile or -interpretation of the Controller Area Network (CAN) protocol used in -automotive networking. Unlike NMEA 0183 it is frame-based and cannot -be transmitted over serial links. - -While newer marine electronics uses this protocol, general-purpose -GPSes have not adopted it. Thus we do not attempt to document NMEA -2000 here; see <>, <>, and <> instead. - -== NMEA version timeline == - -|======================================================================== -|NMEA 2.00 | January 1992 -|NMEA 2.01 | August 1994 -|NMEA 2.10 | October 1995 -|NMEA 2.20 | January 1997 -|NMEA 2.30 | March 1998 -|NMEA 3.00 | July 2000 -|NMEA 3.01 | January 2002 -|NMEA 4.00 | November 2008 -|NMEA 4.10 | July 2012 -|======================================================================== - -No version earlier than 2.00 is listed or archived on the NMEA website. - -The NMEA 4.00 standard states, provocatively, that it is "in theory" -backwards compatible to 2.00, and that versions before 2.00 are not -forward-compatible <>. - -== NMEA 0183 physical protocol layer == - -The NMEA specification requires a physical-level protocol compatible -with RS422 at 4800bps, 8N1 or 7N2. It is RS422 rather than RS232 -because NMEA expects many navigational devices to feed a common serial -bus. The data encoding is ASCII with the high data bit not used and -zeroed. - -Consumer-grade GPS sensors normally report over an RS232 port or a USB -port emulating an RS232 serial device; some use Bluetooth. Baud rate -is variable, with 9600 probably the most common. Most devices use -8N1; there are rare exceptions that use 7N2 (San Jose Navigation) or -even 8O1 (Trimble). - -== Sentence Mixes and NMEA Variations == - -Most GPS sensors emit only RMC, GSA, GSV, GLL, VTG, and (rarely) ZDA. -Newer ones conforming to NMEA 3.x may emit GBS as well. Other NMEA -sentences are usually only emitted by high-end maritime navigation -systems. - -The form of VTG is incompatibly variable with NMEA version. See -the detailed description of that sentence for details. - -In NMEA 2.3, several sentences (APB, BWC, BWR, GLL, RMA, RMB, RMC, -VTG, WCV, and XTE) got a new last field carrying the signal integrity -information needed by the FAA. (The values in the GGA mode field were -extended to carry this information as well.) Here are the values: - -FAA Mode Indicator - A = Autonomous mode - D = Differential Mode - E = Estimated (dead-reckoning) mode - M = Manual Input Mode - S = Simulated Mode - N = Data Not Valid - P = Precise (4.00 and later) - -This field may be empty. In pre-2.3 versions it is omitted. <> says -that according to the NMEA specification, it dominates the Status field -- -the Status field will be set to "A" (data valid) for Mode Indicators A -and D, and to "V" (data invalid) for all other values of the Mode -Indicator. This is confirmed by <>. - -In NMEA 3.0, the GBS sentence reports a complete set of error estimates. Note -however that many receivers claiming to emit "3.0" or "3.01" don't -actually ship this sentence. - -== NMEA Encoding Conventions == - -Data is transmitted in serial async, 1 start-bit, 8 data-bits, -1 stop-bit, no parity. Data-bits are in least-significant-bit -order. The standard specifies 4800 as the speed, but this is no -longer common. The most-signifacant-bit is always zero. - -An NMEA sentence consists of a start delimiter, followed by a -comma-separated sequence of fields, followed by the character '*' -(ASCII 42), the checksum and an end-of-line marker. - -The start delimiter is normally '$' (ASCII 36). Packets of AIVDM/AIVDO -data, which are otherwise formatted like NMEA, use '!'. Up to 4.00 -these are the only permitted start characters <>. - -The first field of a sentence is called the "tag" and normally -consists of a two-letter talker ID followed by a three-letter -type code. - -Where a numeric latitude or longitude is given, the two digits -immediately to the left of the decimal point are whole minutes, to the -right are decimals of minutes, and the remaining digits to the left of -the whole minutes are whole degrees. - -Eg. 4533.35 is 45 degrees and 33.35 minutes. ".35" of a minute is -exactly 21 seconds. - -Eg. 16708.033 is 167 degrees and 8.033 minutes. ".033" of a minute is -about 2 seconds. - -In NMEA 3.01 (and possibly some earlier versions), the character "^" -(HEX 5E) is reserved as an introducer for two-character hex escapes -using 0-9 and A-F, expressing an ISO 8859-1 (Latin-1) character <>. - -The Checksum is mandatory, and the last field in a sentance. It is -the 8-bit XOR of all characters in the sentance, excluding the "$", "I", -or "*" characters; but including all "," and "^". It is encoded as -two hexadecimal characters (0-9, A-F), the most-significant-nibble -being sent first. - -Sentences are terminated by a sequence. - -Maximum sentence length, including the $ and is 82 bytes. - -According to <>, the NMEA standard requires that a field (such as -altitude, latitude, or longitude) must be left empty when the GPS has -no valid data for it. However, many receivers violate this. It's -common, for example, to see latitude/longitude/altitude figures filled -with zeros when the GPS has no valid data. - -== Dates and times == - -NMEA devices report date and time in UTC, aka GMT, aka Zulu time (as -opposed to local time). But the way this report is computed results -in some odd bugs and inaccuracies. - -Date and time in GPS is represented as number of weeks from the start -of zero second of 6 January 1980, plus number of seconds into the -week. GPS time is not leap-second corrected, though satellites also -broadcast a current leap-second correction which may be updated on -three-month boundaries according to rotational bulletins issued by the -International Earth Rotation and Reference Systems Service (IERS). - -The leap-second correction is only included in the multiplexed satellite -subframe broadcast, once every 12.5 minutes. While the satellites do -notify GPSes of upcoming leap-seconds, this notification is not -necessarily processed correctly on consumer-grade devices, and may not -be available at all when a GPS receiver has just cold-booted. Thus, -reported UTC time may be slightly inaccurate between a cold boot or leap -second and the following subframe broadcast. - -GPS date and time are subject to a rollover problem in the 10-bit week -number counter, which will re-zero every 1024 weeks (roughly every 19.6 -years). The last rollover (and the first since GPS went live in 1980) -was in Aug-1999; the next will fall in Apr-2019. The new "CNAV" data -format extends the week number to 13 bits, with the first rollover -occurring in Jan-2137, but this is only used with some newly added GPS -signals, and is unlikely to be usable in most consumer-grade receivers -prior to the 2019 rollover. - -For accurate time reporting, therefore, a GPS requires a supplemental -time references sufficient to identify the current rollover period, -e.g. accurate to within 512 weeks. Many NMEA GPSes have a wired-in -assumption about the UTC time of the last rollover and will thus report -incorrect times outside the rollover period they were designed in. - -For these reasons, NMEA GPSes should not be considered high-quality -references for absolute time. Some do, however, emit pulse-per-second -RS232 signals which can be used to improve the precision of an -external clock. See <> for discussion. - -== Error status indications - -The NMEA sentences in the normal GPS inventory return four kinds of -validity flags: Mode, Status, the Active/Void bit, and in later -versions the FAA indicator mode. The FAA mode field is legally -required and orthogonal to the others. Here's how the first three used -in various sentences: - -[frame="topbot",options="header"] -|======================================================== -| | GPRMC | GPGLL | GPGGA | GPGSA -|Returns A/V | Yes | Yes | No | No -|Returns mode | No | No | No | Yes -|Returns status | No | Yes | Yes | No -|======================================================== - -The "Navigation receiver warning" is 'A' for Active and 'V' for Void. -(or warning). You will see it when either there is no satellite lock, -or to indicate a valid fix that has a DOP too high, or which fails an -elevation test. In the latter case the visible sats are below some -fixed elevation of the horizon (usually 15%, but some GPSes make this -adjustable) making position unreliable due to poor geometry and more -variable signal lag induced by lengthened atmosphere transit. - -Mode is associated with the GSA sentence associated with the last fix. -It reports whether the fix was no good, sufficient for 2D, or -sufficient for 3D (values 1, 2, and 3). - -Status will be 0 when the sample from from which the reporting -sentence was generated does not have a valid fix, 1 when it has -a valid (normal-precision) fix, and 2 when the fig is DGPS corrected -(reducing the base error). - -In addition, some sentences may use empty fields to signify invalid -data. It is not clear whether NMEA 0183 allows this, but real-world -software must cope. - -== Talker IDs == - -NMEA sentences do not identify the individual device that issued -them; the format was originally designed for shipboard multidrop -networks on which it's possible only to broadcast to all devices, not -address a specific one. - -NMEA sentences do, however, include a "talker ID" a two-character -prefix that identifies the type of the transmitting unit. By far the -most common talker ID is "GP", identifying a generic GPS, but all of -the following are well known: - -.Common talker IDs -|================================================================ -|BD | BeiDou (China) -|CD | Digital Selective Calling (DSC) -|EC | Electronic Chart Display & Information System (ECDIS) -|GA | Galileo Positioning System -|GB | BeiDou (China) -|GL | GLONASS, according to IEIC 61162-1 -|GN | Mixed GPS and GLONASS data, according to IEIC 61162-1 -|GP | Global Positioning System receiver -|II | Integrated Instrumentation -|IN | Integrated Navigation -|LC | Loran-C receiver -|QZ | QZSS regional GPS augmentation system (Japan) -|================================================================ - -EC -- ECDIS is a specialized geographical information system intended -to support professional maritime navigation. NMEA talker units -meeting the ECDIS standard use this prefix. Some of these emit GLL. - -II - II is emitted by the NMEA interfaces of several widely-used lines -of marine-navigation electronics. One is the AutoHelm system by -Raymarine; see also <> for the native protocol of these -devices. - -IN -- Some Garmin GPS units use an IN talker ID. - -CD -- Modern marine VHF radios use conventions collectively known as -Digital Selective Calling (DSC). These radios typically take data -from a local position indicating device. This data is used in -conjunction with a unique (FCC assigned) ID to cause your radio to -broadcast your position data to others. Conversely, these radios are -capable of recieving position data of other stations and emitting -sentences indicating other station positions. This lets you plot the -position of other vessels on a chart, for instance. There has been at -least one instance of a DSC enabled radio overloading (mis-using) the -LC talker prefix for this purpose. Otherwise they use the CD prefix. -A vessel's nav system is likely to have both CD and some other -position indicating talker on its bus(es). - -LC - Loran-C is a marine navigation system run by the U.S. government, -which is planning to shut it down in favor of GPS. Some non-Loran -devices emit GLL but use this talker ID for backward-compatibility -reasons, so it may outlast the actual Loran system. - -Until the U.S. Coast Guard terminated the Omega Navigation System in -1997, another common talker prefix was "OM" for an Omega Navigation -System receiver. - -Here is a more complete list of talker ID prefixes. Most are not -relevant to GPS systems. - -Note that talker IDs made obsolete by newer revisions of the -standards may still be emitted by older devices. Support -for them may be present in the GPSD project. - -.Big list of talker IDs -|================================================================ -|AB | Independent AIS Base Station -|AD | Dependent AIS Base Station -|AG | Autopilot - General -|AP | Autopilot - Magnetic -|BN | Bridge navigational watch alarm system -|CC | Computer - Programmed Calculator (obsolete) -|CD | Communications - Digital Selective Calling (DSC) -|CM | Computer - Memory Data (obsolete) -|CS | Communications - Satellite -|CT | Communications - Radio-Telephone (MF/HF) -|CV | Communications - Radio-Telephone (VHF) -|CX | Communications - Scanning Receiver -|DE | DECCA Navigation (obsolete) -|DF | Direction Finder -|DM | Velocity Sensor, Speed Log, Water, Magnetic -|DU | Duplex repeater station -|EC | Electronic Chart Display & Information System (ECDIS) -|EP | Emergency Position Indicating Beacon (EPIRB) -|ER | Engine Room Monitoring Systems -|GP | Global Positioning System (GPS) -|HC | Heading - Magnetic Compass -|HE | Heading - North Seeking Gyro -|HN | Heading - Non North Seeking Gyro -|II | Integrated Instrumentation -|IN | Integrated Navigation -|LA | Loran A (obsolete) -|LC | Loran C (obsolete) -|MP | Microwave Positioning System (obsolete) -|NL | Navigation light controller -|OM | OMEGA Navigation System (obsolete) -|OS | Distress Alarm System (obsolete) -|RA | RADAR and/or ARPA -|SD | Sounder, Depth -|SN | Electronic Positioning System, other/general -|SS | Sounder, Scanning -|TI | Turn Rate Indicator -|TR | TRANSIT Navigation System -|U# | '#' is a digit 0 ... 9; User Configured -|UP | Microprocessor controller -|VD | Velocity Sensor, Doppler, other/general -|VW | Velocity Sensor, Speed Log, Water, Mechanical -|WI | Weather Instruments -|YC | Transducer - Temperature (obsolete) -|YD | Transducer - Displacement, Angular or Linear (obsolete) -|YF | Transducer - Frequency (obsolete) -|YL | Transducer - Level (obsolete) -|YP | Transducer - Pressure (obsolete) -|YR | Transducer - Flow Rate (obsolete) -|YT | Transducer - Tachometer (obsolete) -|YV | Transducer - Volume (obsolete) -|YX | Transducer -|ZA | Timekeeper - Atomic Clock -|ZC | Timekeeper - Chronometer -|ZQ | Timekeeper - Quartz -|ZV | Timekeeper - Radio Update, WWV or WWVH -|================================================================ - -== Satellite IDs == - -Satellites may be identified by one of two different numbers in -sentences such as GSV: a PRN number associated with their radio code, -or an NMEA-ID. - -For satellites 1-32, the GPS constellation, these numbers are the -same. For satellites associated with WAAS (Wide Area Augmentation -System), EGNOS (European Geostationary Navigation Overlay Service), -and MSAS (Multi-functional Satellite Augmentation System), they are -different. - -Here is a table of NMEA-ID allocations above 32 as of March 2010: - -[frame="topbot",options="header"] -|==================================================== -|System |Satellite |PRN |NMEA-ID -|EGNOS |AOR-E |120 |33 -|EGNOS |Artemis |124 |37 -|EGNOS |IOR-W |126 |39 -|MSAS |MTSAT-1 |129 |42 -|EGNOS |IOR-E |131 |44 -|WAAS |AMR |133 |46 -|WAAS |PanAm |135 |48 -|MSAS |MTSAT-2 |137 |50 -|WAAS |Anik |138 |51 -|==================================================== - -In general, NMEA-ID = PRN - 87. Theoretically, all NMEA-emitting -devices should emit NMEA-IDs. In practice, some pass through PRNs. - -Documentation on IDs for GLONASS satellites is scanty. -The manual for one GLONASS-capable receiver has this to say: - -To avoid possible confusion caused by repetition of satellite ID -numbers when using multiple satellite systems, the following -convention has been adopted: - -a. GPS satellites are identified by their PRN numbers, which range from 1 to 32. - -b. The numbers 33-64 are reserved for WAAS satellites. The WAAS system -PRN numbers are 120-138. The offset from NMEA WAAS SV ID to WAAS PRN -number is 87. A WAAS PRN number of 120 minus 87 yields the SV ID of 33. -The addition of 87 to the SV ID yields the WAAS PRN number. - -c. The numbers 65-96 are reserved for GLONASS satellites. GLONASS -satellites are identified by 64+satellite slot number. The slot -numbers are 1 through 24 for the full constellation of 24 satellites, -this gives a range of 65 through 88. The numbers 89 through 96 are -available if slot numbers above 24 are allocated to on-orbit spares. - -Other sources such as <> confirm that the NMEA standard -assigns NMEA IDs 65-96 to GLONASS. The following -table is our best guess of NMEA usage in 2018: - -[frame="topbot",options="header"] -|==================================================== -| 1 - 32 | GPS -| 33 - 54 | Various SBAS systems (EGNOS, WAAS, SDCM, GAGAN, MSAS) -| 55 - 64 | not used (might be assigned to further SBAS systems) -| 65 - 88 | GLONASS -| 89 - 96 | GLONASS (future extensions?) -| 97 - 119 | not used -| 120 - 151 | not used (SBAS PRNs occupy this range) -| 152 - 158 | Various SBAS systems (EGNOS, WAAS, SDCM, GAGAN, MSAS) -| 159 - 172 | not used -| 173 - 182 | IMES -| 193 - 197 | QZSS -| 196 - 200 | QZSS (future extensions?) -| 201 - 235 | BeiDou (u-blox, not NMEA) -| 301 - 336 | GALILEO -| 401 - 437 | BeiDou (NMEA) -|==================================================== - -GLONASS satellite numbers come in two flavors. If a sentence -has a GL talker ID, expect the skyviews to be GLONASS-only and -in the range 1-32; you must add 64 to get a globally-unique -NMEA ID. If the sentence has a GN talker ID, the device emits -a multi-constellation skyview with GLONASS IDs aleady in -the 65-96 range. - -QZSS is a geosynchronous (*not geostationary*) system of three -(possibly four) satellites in highly eliptical, inclined, -orbits. It is designed to provide coverage in Japan's -urban canyons. - -BeiDou-1 consists of 4 geostationary satellites operated by China, -operational since 2004. Coverage area is the Chinese mainland. -gpsd does not support this, as this requires special hardware, -and prior arrangements with the operator, who calculates and -returns the position fix. - -BeiDou-2 (earlier known as COMPASS) is a system of 35 satellites, -including 5 geostationary for compatability with BeiDou-1. -As of late 2015, coverage is complete over most of Asia and the -West Pacific. It is expected to be fully operational by 2020, by -when coverage area is expected to be worldwide. - -Note that the PRN system is becoming increasingly fragmented and -unworkable. New GPS denote each satellite, and their signals, by their -constellation (gnssID), satellite id in that constellation (svId), and -signal type (sigId). NMEA, as of version 4, has not adapted. - -== Obsolete sentences == - -Note that sentances made obsolete by newer revisions of the -standards may still be emitted by devices. -Support for them may be present in the GPSD project. - -The following NMEA sentences have been designated "obsolete" in a -publicly available NMEA document dated 2009. - -|================================================================ -|APA | Autopilot Sentence "A" -|BER | Bearing & Distance to Waypoint, Dead Reckoning, Rhumb Line -|BPI | Bearing & Distance to Point of Interest -|DBK | Depth Below Keel -|DBS | Depth Below Surface -| -|DRU | Dual Doppler Auxiliary Data -|GDA | Dead Reckoning Positions -|GLA | Loran-C Positions -|GOA | OMEGA Positions -|GXA | TRANSIT Positions -|GTD | Geographical Position, Loran-C TDs -|GXA | TRANSIT Position -|HCC | Compass Heading -|HCD | Heading and Deviation -|HDM | Heading, Magnetic -|HDT | Heading, True -|HVD | Magnetic Variation, Automatic -|HVM | Magnetic Variation, Manually Set -|IMA | Vessel Identification -|MDA | Meteorological Composite -|MHU | Humidity -|MMB | Barometer -|MTA | Air Temperature -|MWH | Wave Height -|MWS | Wind & Sea State -| -|Rnn | Routes -|SBK | Loran-C Blink Status -|SCY | oran-C Cycle Lock Status -|SCD | Loran-C ECDs -|SDB | Loran-C Signal Strength -|SGD | Position Accuracy Estimate -|SGR | Loran-C Chain Identifier -|SIU | Loran-C Stations in Use -|SLC | Loran-C Status -|SNC | Navigation Calculation Basis -|SNU | Loran-C SNR Status -|SPS | Loran-C Predicted Signal Strength -|SSF | Position Correction Offset -|STC | Time Constant -|STR | Tracking Reference -|SYS | Hybrid System Configuration -|================================================================ - -== NMEA-Standard Sentences == - -Here are the NMEA-standard sentences we know about: - -=== AAM - Waypoint Arrival Alarm === - -This sentence is generated by some units to indicate the status of -arrival (entering the arrival circle, or passing the perpendicular of -the course line) at the destination waypoint. - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 - | | | | | | - $--AAM,A,A,x.x,N,c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Status, BOOLEAN, A = Arrival circle entered, V = not passed -2. Status, BOOLEAN, A = perpendicular passed at waypoint, V = not passed -3. Arrival circle radius -4. Units of radius, nautical miles -5. Waypoint ID -6. Checksum - -Example: GPAAM,A,A,0.10,N,WPTNME*43 - -WPTNME is the waypoint name. - -=== ALM - GPS Almanac Data === - -This sentence expresses orbital data for a specified GPS satellite. - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - | | | | | | | | | | | | | | | | - $--ALM,x.x,x.x,xx,x.x,hh,hhhh,hh,hhhh,hhhh,hhhhhh,hhhhhh,hhhhhh,hhhhhh,hhh,hhh,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Total number of messages -2. Message Number -3. Satellite PRN number (01 to 32) -4. GPS Week Number -5. SV health, bits 17-24 of each almanac page -6. Eccentricity -7. Almanac Reference Time -8. Inclination Angle -9. Rate of Right Ascension -10. Root of semi-major axis -11. Argument of perigee -12. Longitude of ascension node -13. Mean anomaly -14. F0 Clock Parameter -15. F1 Clock Parameter -16. Checksum - -Fields 5 through 15 are dumped as raw hex. - -Example: - -$GPALM,1,1,15,1159,00,441d,4e,16be,fd5e,a10c9f,4a2da4,686e81,58cbe1,0a4,001*5B - -=== APA - Autopilot Sentence "A" === - -This sentence is sent by some GPS receivers to allow them to be used -to control an autopilot unit. This sentence is commonly used by -autopilots and contains navigation receiver warning flag status, -cross-track-error, waypoint arrival status, initial bearing from -origin waypoint to the destination, continuous bearing from present -position to destination and recommended heading-to-steer to -destination waypoint for the active navigation leg of the journey. - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 11 - | | | | | | | | | | | - $--APA,A,A,x.xx,L,N,A,A,xxx,M,c---c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Status - V = Loran-C Blink or SNR warning - V = general warning flag or other navigation systems when a reliable - fix is not available -2. Status - V = Loran-C Cycle Lock warning flag - A = OK or not used -3. Cross Track Error Magnitude -4. Direction to steer, L or R -5. Cross Track Units (Nautic miles or kilometers) -6. Status - A = Arrival Circle Entered -7. Status - A = Perpendicular passed at waypoint -8. Bearing origin to destination -9. M = Magnetic, T = True -10. Destination Waypoint ID -11. checksum - -Example: $GPAPA,A,A,0.10,R,N,V,V,011,M,DEST,011,M*82 - -=== APB - Autopilot Sentence "B" === - -This is a fixed form of the APA sentence with some ambiguities removed. - -Note: Some autopilots, Robertson in particular, misinterpret "bearing -from origin to destination" as "bearing from present position to -destination". This is likely due to the difference between the APB -sentence and the APA sentence. for the APA sentence this would be the -correct thing to do for the data in the same field. APA only differs -from APB in this one field and APA leaves off the last two fields -where this distinction is clearly spelled out. This will result in -poor performance if the boat is sufficiently off-course that the two -bearings are different. - 13 15 ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 11 12| 14| - | | | | | | | | | | | | | | | - $--APB,A,A,x.x,a,N,A,A,x.x,a,c--c,x.x,a,x.x,a*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Status - V = Loran-C Blink or SNR warning - V = general warning flag or other navigation systems when a reliable - fix is not available -2. Status - V = Loran-C Cycle Lock warning flag - A = OK or not used -3. Cross Track Error Magnitude -4. Direction to steer, L or R -5. Cross Track Units, N = Nautical Miles -6. Status - A = Arrival Circle Entered -7. Status - A = Perpendicular passed at waypoint -8. Bearing origin to destination -9. M = Magnetic, T = True -10. Destination Waypoint ID -11. Bearing, present position to Destination -12. M = Magnetic, T = True -13. Heading to steer to destination waypoint -14. M = Magnetic, T = True -15. Checksum - -Example: $GPAPB,A,A,0.10,R,N,V,V,011,M,DEST,011,M,011,M*82 - -=== BOD - Bearing - Waypoint to Waypoint === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--BOD,x.x,T,x.x,M,c--c,c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Bearing Degrees, TRUE -2. T = True -3. Bearing Degrees, Magnetic -4. M = Magnetic -5. TO Waypoint -6. FROM Waypoint -7. Checksum - -Example 1: $GPBOD,099.3,T,105.6,M,POINTB,*01 - -Waypoint ID: "POINTB" Bearing 99.3 True, 105.6 Magnetic This sentence -is transmitted in the GOTO mode, without an active route on your -GPS. WARNING: this is the bearing from the moment you press enter in -the GOTO page to the destination waypoint and is NOT updated -dynamically! To update the information, (current bearing to waypoint), -you will have to press enter in the GOTO page again. - -Example 2: $GPBOD,097.0,T,103.2,M,POINTB,POINTA*52 - -This sentence is transmitted when a route is active. It contains the -active leg information: origin waypoint "POINTA" and destination -waypoint "POINTB", bearing between the two points 97.0 True, 103.2 -Magnetic. It does NOT display the bearing from current location to -destination waypoint! WARNING Again this information does not change -until you are on the next leg of the route. (The bearing from POINTA -to POINTB does not change during the time you are on this leg.) - -This sentence has been replaced by BWW in NMEA 4.00 (and posssibly -earlier versions) <>. - -=== BWC - Bearing & Distance to Waypoint - Great Circle === - ------------------------------------------------------------------------------- - 12 - 1 2 3 4 5 6 7 8 9 10 11| 13 14 - | | | | | | | | | | | | | | - $--BWC,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x.x,T,x.x,M,x.x,N,c--c,m,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. UTCTime -2. Waypoint Latitude -3. N = North, S = South -4. Waypoint Longitude -5. E = East, W = West -6. Bearing, True -7. T = True -8. Bearing, Magnetic -9. M = Magnetic -10. Nautical Miles -11. N = Nautical Miles -12. Waypoint ID -13. FAA mode indicator (NMEA 2.3 and later, optional) -14. Checksum - -Example 1: $GPBWC,081837,,,,,,T,,M,,N,*13 - -Example 2: GPBWC,220516,5130.02,N,00046.34,W,213.8,T,218.0,M,0004.6,N,EGLM*11 - -=== BWR - Bearing and Distance to Waypoint - Rhumb Line === - ------------------------------------------------------------------------------- - 11 - 1 2 3 4 5 6 7 8 9 10 | 12 13 - | | | | | | | | | | | | | - $--BWR,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x.x,T,x.x,M,x.x,N,c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. UTCTime -2. Waypoint Latitude -3. N = North, S = South -4. Waypoint Longitude -5. E = East, W = West -6. Bearing, True -7. T = True -8. Bearing, Magnetic -9. M = Magnetic -10. Nautical Miles -11. N = Nautical Miles -12. Waypoint ID -13. Checksum - -=== BWW - Bearing - Waypoint to Waypoint === - -Bearing calculated at the FROM waypoint. - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--BWW,x.x,T,x.x,M,c--c,c--c*hh ------------------------------------------------------------------------------- - - Field Number: -1. Bearing Degrees, TRUE -2. T = True -3. Bearing Degrees, Magnetic -4. M = Magnetic -5. TO Waypoint -6. FROM Waypoint -7. Checksum - -=== DBK - Depth Below Keel === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--DBK,x.x,f,x.x,M,x.x,F*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Depth, feet -2. f = feet -3. Depth, meters -4. M = meters -5. Depth, Fathoms -6. F = Fathoms -7. Checksum - -=== DBS - Depth Below Surface === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--DBS,x.x,f,x.x,M,x.x,F*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Depth, feet -2. f = feet -3. Depth, meters -4. M = meters -5. Depth, Fathoms -6. F = Fathoms -7. Checksum - -=== DBT - Depth below transducer === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--DBT,x.x,f,x.x,M,x.x,F*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Depth, feet -2. f = feet -3. Depth, meters -4. M = meters -5. Depth, Fathoms -6. F = Fathoms -7. Checksum - -In real-world sensors, sometimes not all three conversions are reported. -So you might see something like $SDDBT,,f,22.5,M,,F*cs - -Example: $SDDBT,7.8,f,2.4,M,1.3,F*0D - -=== DCN - Decca Position === - ------------------------------------------------------------------------------- - 11 13 16 - 1 2 3 4 5 6 7 8 9 10| 12| 14 15| 17 - | | | | | | | | | | | | | | | | | - $--DCN,xx,cc,x.x,A,cc,x.x,A,cc,x.x,A,A,A,A,x.x,N,x*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Decca chain identifier -2. Red Zone Identifier -3. Red Line Of Position -4. Red Master Line Status -5. Green Zone Identifier -6. Green Line Of Position -7. Green Master Line Status -8. Purple Zone Identifier -9. Purple Line Of Position -10. Purple Master Line Status -11. Red Line Navigation Use -12. Green Line Navigation Use -13. Purple Line Navigation Use -14. Position Uncertainity -15. N = Nautical Miles -16. Fix Data Basis - - 1 = Normal Pattern - - 2 = Lane Identification Pattern - - 3 = Lane Identification Transmissions -17. Checksum - -(The DCN sentence is obsolete as of 3.01) - -=== DPT - Depth of Water === - ------------------------------------------------------------------------------- - 1 2 3 - | | | - $--DPT,x.x,x.x*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Depth, meters -2. Offset from transducer, - positive means distance from tansducer to water line - negative means distance from transducer to keel -3. Checksum - -This sentence was incorrectly titled "Heading - Deviation & Variation" -in <>. It's documented at - - -Example: $INDPT,2.3,0.0*46 - -=== DTM - Datum Reference === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 - | | | | | | | | | - $ --DTM,ref,x,llll,c,llll,c,aaa,ref*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Local datum code. -2. Local datum subcode. May be blank. -3. Latitude offset (minutes) -4. N or S -5. Longitude offset (minutes) -6. E or W -7. Altitude offset in meters -8. Datum name. What's usually seen here is "W84", the standard - WGS84 datum used by GPS. -9. Checksum. - -Example: $GPDTM,W84,C*52 - -=== FSI - Frequency Set Information === - -Set (or report) frequency, mode of operation and transmitter power level of a -radiotelephone. - ------------------------------------------------------------------------------- - 1 2 3 4 5 - | | | | | - $--FSI,xxxxxx,xxxxxx,c,x*hh ------------------------------------------------------------------------------- - - Field Number: -1. Transmitting Frequency -2. Receiving Frequency -3. Communications Mode (NMEA Syntax 2) -4. Power Level -5. Checksum - -=== GBS - GPS Satellite Fault Detection === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 - | | | | | | | | | - $--GBS,hhmmss.ss,x.x,x.x,x.x,x.x,x.x,x.x,x.x*hh ------------------------------------------------------------------------------- - -Field Number: - -1. UTC time of the GGA or GNS fix associated with this sentence -2. Expected error in latitude (meters) -3. Expected error in longitude (meters) -4. Expected error in altitude (meters) -5. PRN of most likely failed satellite -6. Probability of missed detection for most likely failed satellite -7. Estimate of bias in meters on most likely failed satellite -8. Standard deviation of bias estimate -9. Checksum - -Note: Source <> describes a proprietary extension of GBS with -a 9th data field. The 8-field version is in NMEA 3.0. - -Example: $GPGBS,125027,23.43,M,13.91,M,34.01,M*07 - -=== GGA - Global Positioning System Fix Data === - -This is one of the sentences commonly emitted by GPS units. - -Time, Position and fix related data for a GPS receiver. - ------------------------------------------------------------------------------- - 11 - 1 2 3 4 5 6 7 8 9 10 | 12 13 14 15 - | | | | | | | | | | | | | | | - $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Universal Time Coordinated (UTC) -2. Latitude -3. N or S (North or South) -4. Longitude -5. E or W (East or West) -6. GPS Quality Indicator, - - 0 - fix not available, - - 1 - GPS fix, - - 2 - Differential GPS fix - (values above 2 are 2.3 features) - - 3 = PPS fix - - 4 = Real Time Kinematic - - 5 = Float RTK - - 6 = estimated (dead reckoning) - - 7 = Manual input mode - - 8 = Simulation mode -7. Number of satellites in view, 00 - 12 -8. Horizontal Dilution of precision (meters) -9. Antenna Altitude above/below mean-sea-level (geoid) (in meters) -10. Units of antenna altitude, meters -11. Geoidal separation, the difference between the WGS-84 earth - ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level - below ellipsoid -12. Units of geoidal separation, meters -13. Age of differential GPS data, time in seconds since last SC104 - type 1 or 9 update, null field when DGPS is not used -14. Differential reference station ID, 0000-1023 -15. Checksum - -Example: - -$GNGGA,001043.00,4404.14036,N,12118.85961,W,1,12,0.98,1113.0,M,-21.3,M,,*47 - -=== GLC - Geographic Position, Loran-C === - -This sentence is obsolete over most of its former coverage area. The -US/Canadian/Russian Loran-C network was shut down in 2010; it is still -as of 2015 in limited use in Europe. Loran-C operations in Norway -will cease from 1st Jan 2016. <> - ------------------------------------------------------------------------------- - 12 14 - 1 2 3 4 5 6 7 8 9 10 11| 13| - | | | | | | | | | | | | | | - $--GLC,xxxx,x.x,a,x.x,a,x.x,a.x,x,a,x.x,a,x.x,a*hh ------------------------------------------------------------------------------- - -Field Number: - -1. GRI Microseconds/10 -2. Master TOA Microseconds -3. Master TOA Signal Status -4. Time Difference 1 Microseconds -5. Time Difference 1 Signal Status -6. Time Difference 2 Microseconds -7. Time Difference 2 Signal Status -8. Time Difference 3 Microseconds -9. Time Difference 3 Signal Status -10. Time Difference 4 Microseconds -11. Time Difference 4 Signal Status -12. Time Difference 5 Microseconds -13. Time Difference 5 Signal Status -14. Checksum - -=== GLL - Geographic Position - Latitude/Longitude === - -This is one of the sentences commonly emitted by GPS units. - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 - | | | | | | | | - $--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,a,m,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Latitude -2. N or S (North or South) -3. Longitude -4. E or W (East or West) -5. Universal Time Coordinated (UTC) -6. Status A - Data Valid, V - Data Invalid -7. FAA mode indicator (NMEA 2.3 and later) -8. Checksum - -Example: $GNGLL,4404.14012,N,12118.85993,W,001037.00,A,A*67 - -=== GNS - Fix data === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 11 12 13 - | | | | | | | | | | | | | -$--GNS,hhmmss.ss,llll.ll,a,yyyyy.yy,a,c--c,xx,x.x,x.x,x.x,x.x,x.x*hh ------------------------------------------------------------------------------- - -Field Number: - -1. UTC -2. Latitude -3. N or S (North or South) -4. Longitude -5. E or W (East or West) -6. Mode indicator (non-null) -7. Total number of satelites in use,00-99 -8. HDROP -9. Antenna altitude, meters, re:mean-sea-level(geoid. -10. Goeidal separation meters -11. Age of diferential data -12. Differential reference station ID -13. Checksum - -The Mode indicator is two or more characters, with the first and second -defined for GPS and GLONASS. Further characters may be defined. For -each system, the character can have a value (table may be incomplete): - -* N = Constellation not in use, or no valid fix -* A = Autonomous (non-differential) -* D = Differential mode -* P = Precise (no degradation, like Selective Availability) -* R = Real Time Kinematic -* F = Float RTK -* E = Estimated (dead reckoning) Mode -* M = Manual Input Mode -* S = Simulator Mode - -Example: $GPGNS,112257.00,3844.24011,N,00908.43828,W,AN,03,10.5,,,,*57 - -=== GRS - GPS Range Residuals === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - | | | | | | | | | | | | | | | - $ --GRS,hhmmss.ss,m,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. TC time of associated GGA fix -2. 0 = Residuals used in GGA, 1 = residuals calculated after GGA -3. Satellite 1 residual in meters -4. Satellite 2 residual in meters -5. Satellite 3 residual in meters -6. Satellite 4 residual in meters (blank if unused) -7. Satellite 5 residual in meters (blank if unused) -8. Satellite 6 residual in meters (blank if unused) -9. Satellite 7 residual in meters (blank if unused) -10. Satellite 8 residual in meters (blank if unused) -11. Satellite 9 residual in meters (blank if unused) -12. Satellite 10 residual in meters (blank if unused) -13. Satellite 11 residual in meters (blank if unused) -14. Satellite 12 residual in meters (blank if unused) -15. Checksum - -The order of satellites MUST match those in the last GSA. - -Example: $GPGRS,024603.00,1,-1.8,-2.7,0.3,,,,,,,,,*6C - -Note that the talker ID may be GP, GL, or GN, depending on if the residuals -are for GPS-only, GLONASS-only, or combined solution, respectively. - -=== GST - GPS Pseudorange Noise Statistics === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 - | | | | | | | | | - $ --GST,hhmmss.ss,x,x,x,x,x,x,x,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. TC time of associated GGA fix -2. Total RMS standard deviation of ranges inputs to the navigation solution -3. Standard deviation (meters) of semi-major axis of error ellipse -4. Standard deviation (meters) of semi-minor axis of error ellipse -5. Orientation of semi-major axis of error ellipse (true north degrees) -6. Standard deviation (meters) of latitude error -7. Standard deviation (meters) of longitude error -8. Standard deviation (meters) of altitude error -9. Checksum - -Example: $GPGST,182141.000,15.5,15.3,7.2,21.8,0.9,0.5,0.8*54 - - -=== GSA - GPS DOP and active satellites === - -This is one of the sentences commonly emitted by GPS units. - ------------------------------------------------------------------------------- - 1 2 3 14 15 16 17 18 - | | | | | | | | - $--GSA,a,a,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x.x,x.x,x.x*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Selection mode: M=Manual, forced to operate in 2D or 3D, A=Automatic, 3D/2D -2. Mode (1 = no fix, 2 = 2D fix, 3 = 3D fix) -3. ID of 1st satellite used for fix -4. ID of 2nd satellite used for fix -5. ID of 3rd satellite used for fix -6. ID of 4th satellite used for fix -7. ID of 5th satellite used for fix -8. ID of 6th satellite used for fix -9. ID of 7th satellite used for fix -10. ID of 8th satellite used for fix -11. ID of 9th satellite used for fix -12. ID of 10th satellite used for fix -13. ID of 11th satellite used for fix -14. ID of 12th satellite used for fix -15. PDOP -16. HDOP -17. VDOP -18. Checksum - -Example: $GNGSA,A,3,80,71,73,79,69,,,,,,,,1.83,1.09,1.47*17 - -=== GSV - Satellites in view === - -This is one of the sentences commonly emitted by GPS units. - -These sentences describe the sky position of a UPS satellite in view. -Typically they're shipped in a group of 2 or 3. - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 n - | | | | | | | | - $--GSV,x,x,x,x,x,x,x,...*hh ------------------------------------------------------------------------------- - -Field Number: - -1. total number of GSV messages to be transmitted in this group -2. 1-origin number of this GSV message within current group -3. total number of satellites in view (leading zeros sent) -4. satellite PRN number (leading zeros sent) -5. elevation in degrees (-90 to 90) (leading zeros sent) -6. azimuth in degrees to true north (000 to 359) (leading zeros sent) -7. SNR in dB (00-99) (leading zeros sent) - more satellite info quadruples like 4-7 - n) checksum - -Example: - $GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74 - $GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74 - $GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D - -Some GPS receivers may emit more than 12 quadruples (more than three -GPGSV sentences), even though NMEA-0813 doesn't allow this. (The -extras might be WAAS satellites, for example.) Receivers may also -report quads for satellites they aren't tracking, in which case the -SNR field will be null; we don't know whether this is formally allowed -or not. - -Example: $GLGSV,3,3,09,88,07,028,*51 - -=== GTD - Geographic Location in Time Differences === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 - | | | | | | - $--GTD,x.x,x.x,x.x,x.x,x.x*hh ------------------------------------------------------------------------------- - -Field Number: - -1. time difference -2. time difference -3. time difference -4. time difference -5. time difference - n) checksum - - -=== GXA - TRANSIT Position - Latitude/Longitude === - -Location and time of TRANSIT fix at waypoint - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 - | | | | | | | | - $--GXA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,c--c,X*hh ------------------------------------------------------------------------------- - -Field Number: - -1. UTC of position fix -2. Latitude -3. East or West -4. Longitude -5. North or South -6. Waypoint ID -7. Satelite number -8. Checksum - -(The GXA sentence is obsolete as of 3.01.) - -=== HDG - Heading - Deviation & Variation === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 - | | | | | | - $--HDG,x.x,x.x,a,x.x,a*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Magnetic Sensor heading in degrees -2. Magnetic Deviation, degrees -3. Magnetic Deviation direction, E = Easterly, W = Westerly -4. Magnetic Variation degrees -5. Magnetic Variation direction, E = Easterly, W = Westerly -6. Checksum - -=== HDM - Heading - Magnetic === - -Vessel heading in degrees with respect to magnetic north produced by -any device or system producing magnetic heading. - ------------------------------------------------------------------------------- - 1 2 3 - | | | - $--HDM,x.x,M*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Heading Degrees, magnetic -2. M = magnetic -3. Checksum - -=== HDT - Heading - True === - -Actual vessel heading in degrees true produced by any device or system -producing true heading. - ------------------------------------------------------------------------------- - 1 2 3 - | | | - $--HDT,x.x,T*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Heading Degrees, true -2. T = True -3. Checksum - -Example: $GPHDT,274.07,T*03 - -=== HFB - Trawl Headrope to Footrope and Bottom === - ------------------------------------------------------------------------------- - 1 2 3 4 5 - | | | | | - $--HFB,x.x,M,y.y,M*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Distance from headrope to footrope -2. Meters (0-100) -3. Distance from headrope to bottom -4. Meters (0-100) -5. Checksum - -From <>. Shown with a "@II" leader rather than "$GP". - -=== HSC - Heading Steering Command === - ------------------------------------------------------------------------------- - 1 2 3 4 5 - | | | | | - $--HSC,x.x,T,x.x,M,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Heading Degrees, True -2. T = True -3. Heading Degrees, Magnetic -4. M = Magnetic -5. Checksum - -<> describes a completely different meaning for this -sentence, having to do with water temperature sensors. It is -unclear which is correct. - -=== ITS - Trawl Door Spread 2 Distance === - ------------------------------------------------------------------------------- - 1 2 3 - | | | - $--ITS,x.x,M*hh ------------------------------------------------------------------------------- - -Field Number) - -1. Second spread distance -2. Meters -3. Checksum. - -From <>. Shown with a "@II" leader rather than "$GP". - -=== LCD - Loran-C Signal Data === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - | | | | | | | | | | | | | | - $--LCD,xxxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx*hh ------------------------------------------------------------------------------- - -Field Number: - -1. GRI Microseconds/10 -2. Master Relative SNR -3. Master Relative ECD -4. Time Difference 1 Microseconds -5. Time Difference 1 Signal Status -6. Time Difference 2 Microseconds -7. Time Difference 2 Signal Status -8. Time Difference 3 Microseconds -9. Time Difference 3 Signal Status -10. Time Difference 4 Microseconds -11. Time Difference 4 Signal Status -12. Time Difference 5 Microseconds -13. Time Difference 5 Signal Status -14. Checksum - -=== MDA - Meteorilogical Composite === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - | | | | | | | | | | | | | | | | | | | | | - $--MDA,n.nn,I,n.nnn,B,n.n,C,n.C,n.n,n,n.n,C,n.n,T,n.n,M,n.n,N,n.n,M*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Barometric pressure, inches of mercury, to the nearest 0.01 inch -2. I = inches of mercury -3. Barometric pressure, bars, to the nearest .001 bar -4. B = bars -5. Air temperature, degrees C, to the nearest 0.1 degree C -6. C = degrees C -7. Water temperature, degrees C (this field left blank by WeatherStation) -8. C = degrees C -9. Relative humidity, percent, to the nearest 0.1 percent -10. Absolute humidity, percent -11. Dew point, degrees C, to the nearest 0.1 degree C -12. C = degrees C -13. Wind direction, degrees True, to the nearest 0.1 degree -14. T = true -15. Wind direction, degrees Magnetic, to the nearest 0.1 degree -16. M = magnetic -17. Wind speed, knots, to the nearest 0.1 knot -18. N = knots -19. Wind speed, meters per second, to the nearest 0.1 m/s -20. M = meters per second -21. Checksum - -Obsolete as of 2009. - -=== MSK - Control for a Beacon Receiver === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 - | | | | | | - $--MSK,nnn,m,nnn,m,nnn*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Frequency to use -2. Frequency mode, A=auto, M=manual -3. Beacon bit rate -4. Bitrate, A=auto, M=manual -5. Frequency for MSS message status (null for no status) -6. Checksum - -=== MSS - Beacon Receiver Status === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 - | | | | | | - $--MSS,nn,nn,fff,bbb,xxx*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Signal strength (dB 1uV) -2. Signal to noise ratio (dB) -3. Beacon frequency (kHz) -4. Beacon data rate (BPS) -5. Unknown integer value -6. Checksum - -Example: $GPMSS,0,0,0.000000,200,*5A - -=== MTW - Mean Temperature of Water === - ------------------------------------------------------------------------------- - 1 2 3 - | | | - $--MTW,x.x,C*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Degrees -2. Unit of Measurement, Celcius -3. Checksum - -<> lists this as "Meteorological Temperature of Water", which -is probably incorrect. - -Example: $INMTW,17.9,C*1B - -=== MWV - Wind Speed and Angle === - ------------------------------------------------------------------------------- - 1 2 3 4 5 - | | | | | - $--MWV,x.x,a,x.x,a*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Wind Angle, 0 to 360 degrees -2. Reference, R = Relative, T = True -3. Wind Speed -4. Wind Speed Units, K/M/N -5. Status, A = Data Valid -6. Checksum - -=== OLN - Omega Lane Numbers === - ------------------------------------------------------------------------------- - 1 2 3 4 - |--------+ |--------+ |--------+ | - $--OLN,aa,xxx,xxx,aa,xxx,xxx,aa,xxx,xxx*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Omega Pair 1 -2. Omega Pair 1 -3. Omega Pair 1 -4. Checksum - -(The OLN sentence is obsolete as of 2.30) - -=== OSD - Own Ship Data === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 - | | | | | | | | | | - $--OSD,x.x,A,x.x,a,x.x,a,x.x,x.x,a*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Heading, degrees true -2. Status, A = Data Valid -3. Vessel Course, degrees True -4. Course Reference -5. Vessel Speed -6. Speed Reference -7. Vessel Set, degrees True -8. Vessel drift (speed) -9. Speed Units -10. Checksum - -=== R00 - Waypoints in active route === - ------------------------------------------------------------------------------- - 1 n - | | - $--R00,c---c,c---c,....*hh ------------------------------------------------------------------------------- - -Field Number: - -1. waypoint ID - -... - -n) checksum - -=== RMA - Recommended Minimum Navigation Information === - ------------------------------------------------------------------------------- - 12 - 1 2 3 4 5 6 7 8 9 10 11| - | | | | | | | | | | | | - $--RMA,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,x.x,x.x,x.x,a*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Blink Warning -2. Latitude -3. N or S -4. Longitude -5. E or W -6. Time Difference A, uS -7. Time Difference B, uS -8. Speed Over Ground, Knots -9. Track Made Good, degrees true -10. Magnetic Variation, degrees -11. E or W -12. Checksum - -=== RMB - Recommended Minimum Navigation Information === - -To be sent by a navigation receiver when a destination waypoint is active. - ------------------------------------------------------------------------------- - 14 - 1 2 3 4 5 6 7 8 9 10 11 12 13| 15 - | | | | | | | | | | | | | | | - $--RMB,A,x.x,a,c--c,c--c,llll.ll,a,yyyyy.yy,a,x.x,x.x,x.x,A,m,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Status, A= Active, V = Void -2. Cross Track error - nautical miles -3. Direction to Steer, Left or Right -4. TO Waypoint ID -5. FROM Waypoint ID -6. Destination Waypoint Latitude -7. N or S -8. Destination Waypoint Longitude -9. E or W -10. Range to destination in nautical miles -11. Bearing to destination in degrees True -12. Destination closing velocity in knots -13. Arrival Status, A = Arrival Circle Entered -14. FAA mode indicator (NMEA 2.3 and later) -15. Checksum - -Example: $GPRMB,A,0.66,L,003,004,4917.24,N,12309.57,W,001.3,052.5,000.5,V*0B - -=== RMC - Recommended Minimum Navigation Information === - -This is one of the sentences commonly emitted by GPS units. - ------------------------------------------------------------------------------- - 12 - 1 2 3 4 5 6 7 8 9 10 11| 13 - | | | | | | | | | | | | | - $--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a,m,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. UTC Time -2. Status, V=Navigation receiver warning A=Valid -3. Latitude -4. N or S -5. Longitude -6. E or W -7. Speed over ground, knots -8. Track made good, degrees true -9. Date, ddmmyy -10. Magnetic Variation, degrees -11. E or W -12. FAA mode indicator (NMEA 2.3 and later) -13. Checksum - -A status of V means the GPS has a valid fix that is below an internal -quality threshold, e.g. because the dilution of precision is too high -or an elevation mask test failed. - -Example: $GNRMC,001031.00,A,4404.13993,N,12118.86023,W,0.146,,100117,,,A*7B - -=== ROT - Rate Of Turn === - ------------------------------------------------------------------------------- - 1 2 3 - | | | - $--ROT,x.x,A*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Rate Of Turn, degrees per minute, "-" means bow turns to port -2. Status, A means data is valid -3. Checksum - -Example: $HEROT,0.0,A*2B - -=== RPM - Revolutions === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 - | | | | | | - $--RPM,a,x,x.x,x.x,A*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Sourse, S = Shaft, E = Engine -2. Engine or shaft number -3. Speed, Revolutions per minute -4. Propeller pitch, % of maximum, "-" means astern -5. Status, A means data is valid -6. Checksum - - -=== RSA - Rudder Sensor Angle === - ------------------------------------------------------------------------------- - 1 2 3 4 5 - | | | | | - $--RSA,x.x,A,x.x,A*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Starboard (or single) rudder sensor, "-" means Turn To Port -2. Status, A means data is valid -3. Port rudder sensor -4. Status, A means data is valid -5. Checksum - -=== RSD - RADAR System Data === - ------------------------------------------------------------------------------- - 14 - 1 2 3 4 5 6 7 8 9 10 11 12 13| - | | | | | | | | | | | | | | - $--RSD,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,a,a*hh ------------------------------------------------------------------------------- - -(Some fields are missing from this description.) - -Field Number: -1. Unknown -2. Unknown -3. Unknown -4. Unknown -5. Unknown -6. Unknown -7. Unknown -8. Unknown -9. Cursor Range From Own Ship -10. Cursor Bearing Degrees Clockwise From Zero -11. Range Scale -12. Range Units -13 Unknown -14. Checksum - -=== RTE - Routes === - ------------------------------------------------------------------------------- - 1 2 3 4 5 x n - | | | | | | | - $--RTE,x.x,x.x,a,c--c,c--c, ..... c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Total number of messages being transmitted -2. Message Number -3. Message mode - c = complete route, all waypoints - w = working route, the waypoint you just left, the waypoint - you're heading to, then all the rest -4. Waypoint ID - -More waypoints follow. Last field is a checksum as usual. - -The Garmin 65 and possibly other units report a $GPR00 in the same format. - -Example: $GPRTE,1,1,c,0*07 - -=== SFI - Scanning Frequency Information === - ------------------------------------------------------------------------------- - 1 2 3 4 x - | | | | | - $--SFI,x.x,x.x,xxxxxx,c .......... xxxxxx,c*hh ------------------------------------------------------------------------------- - -Field Number: -1. Total Number Of Messages -2. Message Number -3. Frequency 1 -4. Mode 1 -x. Checksum - -=== STN - Multiple Data ID === - -This sentence is transmitted before each individual sentence where -there is a need for the Listener to determine the exact source of data -in the system. Examples might include dual-frequency depthsounding -equipment or equipment that integrates data from a number of sources -and produces a single output. - ------------------------------------------------------------------------------- - 1 2 - | | - $--STN,x.x,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Talker ID Number -2. Checksum - -=== TDS - Trawl Door Spread Distance === - ------------------------------------------------------------------------------- - 1 2 3 - | | | - $--TDS,x.x,M*hh ------------------------------------------------------------------------------- - -Field Number) - -1. Distance between trawl doors -2. Meters (0-300) -3. Checksum. - -From <>. Shown with a "@II" leader rather than "$GP". - -=== TFI - Trawl Filling Indicator === - ------------------------------------------------------------------------------- - 1 2 3 4 - | | | | - $--TFI,x,y,z*hh ------------------------------------------------------------------------------- - -Field number: - -1. Catch sensor #1 (0 = off, 1 = on, 2 = no answer) -2. Catch sensor #2 (0 = off, 1 = on, 2 = no answer) -3. Catch sensor #3 (0 = off, 1 = on, 2 = no answer) - -From <>. Shown with a "@II" leader rather than "$GP". - -=== TPC - Trawl Position Cartesian Coordinates === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--TPC,x,M,y,P,z.z,M*hh, ------------------------------------------------------------------------------- - -Field Number: - -1. Horizontal distance from the vessel center line -2. Meters -3. Horizontal distance from the transducer to the trawl along the - vessel center line. The value is normally positive assuming the - trawl is located behind the vessel. -4. Meters -5. Depth of the trawl below the surface -6. Meters -7. Checksum - -From <>. Shown with a "@II" leader rather than "$GP". -This entry actually merges their TPC description with another -entry labeled (apparently incorrectly) TPT, which differs from the -TPT shown below. - -=== TPR - Trawl Position Relative Vessel === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--TPR,x,M,y,P,z.z,M*hh, ------------------------------------------------------------------------------- - -Field Number: - -1. Horizontal range relative to target -2. Meters (0-4000) -3. Bearing to target relative to vessel heading. Resolution is one degree. -4. Separator -5. Depth of trawl below the surface -6. Meters (0-2000) -7. Checksum - -From <>. Shown with a "@II" leader rather than "$GP". - -=== TPT - Trawl Position True === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--TPT,x,M,y,P,z.z,M*hh, ------------------------------------------------------------------------------- - -Field Number: - -1. Horizontal range relative to target -2. Meters (0-4000) -3. True bearing to taget (ie. relative north). Resolution is one degree. -4. Separator -5. Depth of trawl below the surface -6. Meters (0-2000) -7. Checksum - -From <>. Shown with a "@II" leader rather than "$GP". - -=== TRF - TRANSIT Fix Data === - ------------------------------------------------------------------------------- - 13 - 1 2 3 4 5 6 7 8 9 10 11 12| - | | | | | | | | | | | | | - $--TRF,hhmmss.ss,xxxxxx,llll.ll,a,yyyyy.yy,a,x.x,x.x,x.x,x.x,xxx,A*hh ------------------------------------------------------------------------------- - -Field Number: - -1. UTC Time -2. Date, ddmmyy -3. Latitude -4. N or S -5. Longitude -6. E or W -7. Elevation Angle -8. Number of iterations -9. Number of Doppler intervals -10. Update distance, nautical miles -11. Satellite ID -12. Data Validity -13. Checksum - -(The TRF sentence is obsolete as of 2.3.0) - -=== TTM - Tracked Target Message === - ------------------------------------------------------------------------------- - 11 13 - 1 2 3 4 5 6 7 8 9 10| 12| 14 - | | | | | | | | | | | | | | - $--TTM,xx,x.x,x.x,a,x.x,x.x,a,x.x,x.x,a,c--c,a,a*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Target Number (0-99) -2. Target Distance -3. Bearing from own ship -4. Bearing Units -5. Target Speed -6. Target Course -7. Course Units -8. Distance of closest-point-of-approach -9. Time until closest-point-of-approach "-" means increasing -10. "-" means increasing -11. Target name -12. Target Status -13. Reference Target -14. Checksum - -<> gives this in a slightly different form, with 14th and -15th fields conveying time of observation and whether target -acquisition was automatic or manual. - -=== VBW - Dual Ground/Water Speed === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--VBW,x.x,x.x,A,x.x,x.x,A*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Longitudinal water speed, "-" means astern -2. Transverse water speed, "-" means port -3. Status, A = Data Valid -4. Longitudinal ground speed, "-" means astern -5. Transverse ground speed, "-" means port -6. Status, A = Data Valid -7. Checksum - -=== VDR - Set and Drift === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--VDR,x.x,T,x.x,M,x.x,N*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Degress True -2. T = True -3. Degrees Magnetic -4. M = Magnetic -5. Knots (speed of current) -6. N = Knots -7. Checksum - -=== VHW - Water speed and heading === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 - | | | | | | | | | - $--VHW,x.x,T,x.x,M,x.x,N,x.x,K*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Degress True -2. T = True -3. Degrees Magnetic -4. M = Magnetic -5. Knots (speed of vessel relative to the water) -6. N = Knots -7. Kilometers (speed of vessel relative to the water) -8. K = Kilometers -9. Checksum - -<> describes a different format in which the first three -fields are water-temperature measurements. It's not clear which -is correct. - -=== VLW - Distance Traveled through Water === - ------------------------------------------------------------------------------- - 1 2 3 4 5 - | | | | | - $--VLW,x.x,N,x.x,N*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Total cumulative distance -2. N = Nautical Miles -3. Distance since Reset -4. N = Nautical Miles -5. Checksum - -=== VPW - Speed - Measured Parallel to Wind === - ------------------------------------------------------------------------------- - 1 2 3 4 5 - | | | | | - $--VPW,x.x,N,x.x,M*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Speed, "-" means downwind -2. N = Knots -3. Speed, "-" means downwind -4. M = Meters per second -5. Checksum - -=== VTG - Track made good and Ground speed === - -This is one of the sentences commonly emitted by GPS units. - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 - | | | | | | | | | | - $--VTG,x.x,T,x.x,M,x.x,N,x.x,K,m,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Track Degrees -2. T = True -3. Track Degrees -4. M = Magnetic -5. Speed Knots -6. N = Knots -7. Speed Kilometers Per Hour -8. K = Kilometers Per Hour -9. FAA mode indicator (NMEA 2.3 and later) -10. Checksum - -Note: in some older versions of NMEA 0183, the sentence looks like this: - ------------------------------------------------------------------------------- - 1 2 3 4 5 - | | | | | - $--VTG,x.x,x,x.x,x.x,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. True course over ground (degrees) 000 to 359 -2. Magnetic course over ground 000 to 359 -3. Speed over ground (knots) 00.0 to 99.9 -4. Speed over ground (kilometers) 00.0 to 99.9 -5. Checksum - -The two forms can be distinguished by field 2, which will be -the fixed text 'T' in the newer form. The new form appears -to have been introduced with NMEA 3.01 in 2002. - -Some devices, such as those described in <>, leave the -magnetic-bearing fields 3 and 4 empty. - -Example: $GPVTG,220.86,T,,M,2.550,N,4.724,K,A*34 - -=== VWR - Relative Wind Speed and Angle === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 - | | | | | | | | | - $--VWR,x.x,a,x.x,N,x.x,M,x.x,K*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Wind direction magnitude in degrees -2. Wind direction Left/Right of bow -3. Speed -4. N = Knots -5. Speed -6. M = Meters Per Second -7. Speed -8. K = Kilometers Per Hour -9. Checksum - -=== WCV - Waypoint Closure Velocity === - ------------------------------------------------------------------------------- - 1 2 3 4 - | | | | - $--WCV,x.x,N,c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Velocity -2. N = knots -3. Waypoint ID -4. Checksum - -=== WNC - Distance - Waypoint to Waypoint === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--WNC,x.x,N,x.x,K,c--c,c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Distance, Nautical Miles -2. N = Nautical Miles -3. Distance, Kilometers -4. K = Kilometers -5. TO Waypoint -6. FROM Waypoint -7. Checksum - -=== WPL - Waypoint Location === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 - | | | | | | - $--WPL,llll.ll,a,yyyyy.yy,a,c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Latitude -2. N or S (North or South) -3. Longitude -4. E or W (East or West) -5. Waypoint name -6. Checksum - -=== XDR - Transducer Measurement === - ------------------------------------------------------------------------------- - 1 2 3 4 n - | | | | | - $--XDR,a,x.x,a,c--c, ..... *hh ------------------------------------------------------------------------------- - -Field Number: - -1. Transducer Type -2. Measurement Data -3. Units of measurement -4. Name of transducer - -There may be any number of quadruplets like this, each describing a -sensor. The last field will be a checksum as usual. - -Example: - -$HCXDR,A,171,D,PITCH,A,-37,D,ROLL,G,367,,MAGX,G,2420,,MAGY,G,-8984,,MAGZ*41 - -=== XTE - Cross-Track Error, Measured === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--XTE,A,A,x.x,a,N,m,*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Status - - V = Loran-C Blink or SNR warning - - V = general warning flag or other navigation systems when a reliable - fix is not available -2. Status - - V = Loran-C Cycle Lock warning flag - - A = OK or not used -3. Cross Track Error Magnitude -4. Direction to steer, L or R -5. Cross Track Units, N = Nautical Miles -6. FAA mode indicator (NMEA 2.3 and later, optional) -7. Checksum - -Example: $GPXTE,V,V,,,N,S*43 - -=== XTR - Cross Track Error - Dead Reckoning === - ------------------------------------------------------------------------------- - 1 2 3 4 - | | | | - $--XTR,x.x,a,N*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Magnitude of cross track error -2. Direction to steer, L or R -3. Units, N = Nautical Miles -4. Checksum - -=== ZDA - Time & Date - UTC, day, month, year and local time zone === - -This is one of the sentences commonly emitted by GPS units. - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $--ZDA,hhmmss.ss,xx,xx,xxxx,xx,xx*hh ------------------------------------------------------------------------------- - -Field Number: - -1. UTC time (hours, minutes, seconds, may have fractional subsecond) -2. Day, 01 to 31 -3. Month, 01 to 12 -4. Year (4 digits) -5. Local zone description, 00 to +- 13 hours -6. Local zone minutes description, apply same sign as local hours -7. Checksum - -Example: $GPZDA,160012.71,11,03,2004,-1,00*7D - -=== ZFO - UTC & Time from origin Waypoint === - ------------------------------------------------------------------------------- - 1 2 3 4 - | | | | - $--ZFO,hhmmss.ss,hhmmss.ss,c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Universal Time Coordinated (UTC) -2. Elapsed Time -3. Origin Waypoint ID -4. Checksum - -=== ZTG - UTC & Time to Destination Waypoint === - ------------------------------------------------------------------------------- - 1 2 3 4 - | | | | - $--ZTG,hhmmss.ss,hhmmss.ss,c--c*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Universal Time Coordinated (UTC) -2. Time Remaining -3. Destination Waypoint ID -4. Checksum - -=== Other sentences === - -There is evidence for the existence of the following NMEA sentences -on the Web: - -|====================================================== -|ACK - Alarm Acknowldgement -|ADS - Automatic Device Status -|AKD - Acknowledge Detail Alarm Condition -|ALA - Set Detail Alarm Condition -|ASD - Autopilot System Data -|BEC - Bearing & Distance to Waypoint - Dead Reckoning -|CEK - Configure Encryption Key Command -|COP - Configure the Operational Period, Command -|CUR - Water Current Layer -|DCR - Device Capability Report -|DDC - Display Dimming Control -|DOR - Door Status Detection -|DSC - Digital Selective Calling Information -|DSE - Extended DSC -|DSI - DSC Transponder Initiate -|DSR - DSC Transponder Response -|ETL - Engine Telegraph Operation Status -|EVE - General Event Message -|FIR - Fire Detection -|MWD - Wind Direction & Speed -|TLL - Target Latitude and Longitude -|WDR - Distance to Waypoint - Rhumb Line -|WDC - Distance to Waypoint - Great Circle -|ZDL - Time and Distance to Variable Point -|====================================================== - -$CDDSC is described in <>. - -== Vendor extensions == - -This list is very incomplete. - -=== PASHR - RT300 proprietary roll and pitch sentence === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 9 10 11 12 - | | | | | | | | | | | | -$PASHR,hhmmss.sss,hhh.hh,T,rrr.rr,ppp.pp,xxx.xx,a.aaa,b.bbb,c.ccc,d,e*hh ------------------------------------------------------------------------------- - -Field number: - -1. hhmmss.sss - UTC time -2. hhh.hh - Heading in degrees -3. T - flag to indicate that the Heading is True Heading (i.e. to True North) -4. rrr.rr - Roll Angle in degrees -5. ppp.pp - Pitch Angle in degrees -6. xxx.xx - Heave -7. a.aaa - Roll Angle Accuracy Estimate (Stdev) in degrees -8. b.bbb - Pitch Angle Accuracy Estimate (Stdev) in degrees -9. c.ccc - Heading Angle Accuracy Estimate (Stdev) in degrees -10. d - Aiding Status -11. e - IMU Status -12. hh - Checksum - -<> describes this sentence as NMEA, though other sources say it -is Ashtech proprietary and describe a different format. - -Example: - -$PASHR,085335.000,224.19,T,-01.26,+00.83,+00.00,0.101,0.113,0.267,1,0*06 - -=== PGRME - Garmin Estimated Error === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 - | | | | | | | - $PGRME,hhh,M,vvv,M,ttt,M*hh ------------------------------------------------------------------------------- - -Field Number: - -1. Estimated horizontal position error (HPE), -2. M=meters -3. Estimated vertical position error (VPE) -4. M=meters -5. Overall spherical equivalent position error -6. M=meters -7. Checksum - -Example: $PGRME,15.0,M,45.0,M,25.0,M*22 - -=== PMGNST - Magellan Status === - ------------------------------------------------------------------------------- - 1 2 3 4 5 6 7 8 - | | | | | | | | - $PMGNST,xx.xx,m,t,nnn,xx.xx,nnn,nn,c ------------------------------------------------------------------------------- - -Field Number: - -1. Firmware version number? -2. Mode (1 = no fix, 2 = 2D fix, 3 = 3D fix) -3. T if we have a fix -4. numbers change - unknown -5. time left on the GPS battery in hours -6. numbers change (freq. compensation?) -7. PRN number receiving current focus -8. nmea_checksum - -Only supported on Magellan GPSes. - -=== PRWIZCH - Rockwell Channel Status === - ------------------------------------------------------------------------------- - $PRWIZCH,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,n,s,c*hh ------------------------------------------------------------------------------- - -Fields consist of 12 pairs of a satellite PRN followed by a -signal quality number in the range 0-7 (0 worst, 7 best). - -Only emitted by the now-obsolete Zodiac (Rockwell) chipset. - -=== PUBX 00 - u-blox Lat/Long Position Data === - ------------------------------------------------------------------------------- - $PUBX,00,hhmmss.ss,Latitude,N,Longitude,E,AltRef,NavStat,Hacc,Vacc,SOG,COG,Vvel,+ageC,HDOP,VDOP,TDOP,GU,RU,DR,*hh ------------------------------------------------------------------------------- - -Example: - -$PUBX,00,081350.00,4717.113210,N,00833.915187,E,546.589,G3,2.1,2.0,0.007,77.52,0+.007,,0.92,1.19,0.77,9,0,0*5F - -Only emitted by u-blox Antaris chipset. - -=== PUBX 01 - u-blox UTM Position Data === - -The $PUBX,01 is a UTM (Universal Transverse Mercator projection) version -of the $PUBX,00 sentence. - ------------------------------------------------------------------------------- -$PUBX,01,hhmmss.ss,Easting,E,Northing,N,AltMSL,NavStat,Hacc,Vacc,SOG,COG,Vvel,ag+eC,HDOP,VDOP,TDOP,GU,RU,DR,*hh ------------------------------------------------------------------------------- - -Example: - -$PUBX,01,075142.00,467125.245,E,5236949.763,N,498.235,G3,2.1,1.9,0.005,85.63,0.0+00,,0.78,0.90,0.52,12,0,0*65 - -Only emitted by u-blox Antaris chipset. - -=== PUBX 03 - u-blox Satellite Status === - ------------------------------------------------------------------------------- - $PUBX,03,GT{,ID,s,AZM,EL,SN,LK},*hh ------------------------------------------------------------------------------- - -Example: - -$PUBX,03,11,23,-,,,45,010,29,-,,,46,013,07,-,,,42,015,08,U,067,31,42,025,10,U,19+5,33,46,026,18,U,326,08,39,026,17,-,,,32,015,26,U,306,66,48,025,27,U,073,10,36,+026,28,U,089,61,46,024,15,-,,,39,014*0D - -Only emitted by u-blox Antaris chipset. - -(There's no PUBX 02) - -=== PUBX 04 - u-blox Time of Day and Clock Information === - ------------------------------------------------------------------------------- -$PUBX,04,hhmmss.ss,ddmmyy,UTC_TOW,week,reserved,Clk_B,Clk_D,PG,*hh ------------------------------------------------------------------------------- - -Example: - -$PUBX,04,073731.00,091202,113851.00,1196,113851.00,1930035,-2660.664,43,*3C<+LF> - -Only emitted by u-blox Antaris chipset. - -=== TMVTD - Transas VTS / SML tracking system report === - ------------------------------------------------------------------------------- -$TMVTD,DDMMYY,hhmmss.ss,a,xxxx,c—c,llll.llll,a,yyyyy.yyyy,a,x.x,a,x.x,a,a*hh ------------------------------------------------------------------------------- - -‘TM’ indicates message generated by SML tracking system. ‘VTD’ is -name of the message. - -Field Number: - -1. Day/month/year (two-digit year, unknown base century) -2. Hour/minute/second to 0.1 sec precion, UTC. -3. ‘R’ indicates that this is an update for a radar track. No other - values are valid -4. Internal unique ID number. Can’t be changed even when target is - re-identified -5. Target alias. Can be changed when the target identification data is - edited. Symbols “$”, “*” “,” and “.” are not allowed to be used - within the alias word. This field is variable length, at most 21v - characters. -6. Latitude in degrees (two leading digits) and decimal minutes - (trailing digits). -7. N or S for North or South latitude. -8. Longitude in degrees (three leading digits) and decimal minutes - (trailing digits). -9. E or W for East or West longitude. -10. Target course in decimal degrees. -11. Fixed to T, indicates true course. -12. Target speed in decimal knots. -13. Fixed to N, indicates decimal speed in knots. -14. T or D. T = tracked, D = dropped. Message with status - “dropped” is sent only once after target is dropped. -15. NMEA checksum. - -Transas is a mnanufacturer of proprietary ECDIS systems. - -Described in <>, actually a Maltese government document. - -== References == - -[bibliography] -- [[[BETKE]]] - "The NMEA 0183 protocol" - http://www.scribd.com/mcocco/d/6365285-The-NMEA-0183-Protocol - Probably the ancestor of this document. Compiled by Klaus Betke - and dated May 2000 with a revision in 2001. - -- [[[CANBUS]]] - "Wikipedia: CAN bus" - http://en.wikipedia.org/wiki/CAN_bus - -- [[[NMEA2000]]] - "Wikipedia: NMEA 2000" - http://en.wikipedia.org/wiki/NMEA_2000 - -- [[[KEVERSOFT]]] - http://www.keversoft.com/downloads/packetlogger_20120305_explain.txt - -- [[[DEPRIEST]]] - "NMEA data" - http://www.gpsinformation.org/dale/nmea.htm - Used for PMGNST and the FAA mode code. - -- [[[MX521]]] - "MX521 GPS/DGPS Sensor Installation Manual" - http://www.mx-marine.com/downloads/MX521_Install_manual_051804.pdf - Used for GBS, GRS. - -- [[[MX535]]] - "MX535 UAIS Ship Borne Class A Transponder Unit Techical & Installation Manual" - http://www.mx-marine.com/downloads/mx535/MX535_Tech_Manual_Rev_E.pdf - Used for GNS. - -- [[[ZODIAC]]] - "Zodiac Serial Data Interface Specification" - http://users.rcn.com/mardor/serial.pdf - Used for PRWIZCH. - -- [[[GH79L4N]]] - "Specifications for GPS Receiver GH-79L4-N" - http://www.tecsys.de/db/gps/gh79l1an_intant.pdf - Used for GPDTM. - -- [[[GIDS]]] - "GPS - NMEA sentence information" - http://aprs.gids.nl/nmea/ - Used for BWC, MSK, MSS. - -- [[[NMEAFAQ]]] - "The NMEA FAQ" - http://vancouver-webpages.com/peter/nmeafaq.txt - Used for R00. - -- [[[UNMEA]]] - "Understanding NMEA 0183" - http://pcptpp030.psychologie.uni-regensburg.de/trafficresearch/NMEA0183/ - Source for the claim that NMEA requires undefined data fields to - be empty. - -- [[[NTUM]]] - "NemaTalker User Manual" - http://www.sailsoft.nl/NemaTalker/UserManual/InstrGPS.htm - Source for the claim that Mode Indicator dominates Status. - -- [[[IEC61162-1]]] - "International Standard IEC 61162-1" (preview) - http://domino.iec.ch/preview/info_iec61162-1%7Bed2.0%7Den.pdf - -- [[[SEATALK]]] - "SeaTalk Technical Reference" - http://www.thomasknauf.de/seatalk.htm - -- [[[SATSTAT]]] "NMEA IDs" https://github.com/mvglasow/satstat/wiki/NMEA-IDs - -- [[[GLOBALSAT]]] - "NMEA (National Marine Electronics Association) 0183 Protocol" - http://www.usglobalsat.com/faq_details/NMEA.htm - -- [[[PASHR]]] - "News - NMEA PASHR Output Format Added" - http://www.oxts.com/default.asp?pageRef=76&newsID=69 - -- [[[WAAS]]] - "WAAS Information" - http://gpsinformation.net/exe/waas.html - -- [[[PPS]]] - "Pulse per second" - http://en.wikipedia.org/wiki/Pulse_per_second - -- [[[MALTESE]]] - "Procurement of a Fixed-Wing Maritime Patrol Aircraft" - https://secure2.gov.mt/eprocurement/Tenders/file.ashx?f=9832DB05E65C774258580284031EC72CC315D954A7108B5E. - -- [[NMEA-ADVANCE]] - "NMEA 0183 Advancements" (describes 'P' value of FAA mode) - http://www.nmea.org/Assets/0183_advancements_nmea_oct_1_2010%20(2).pdf - -- [[CDDSC]] - "Data Interface in Digital Selective Calling Class-D Radios" - http://continuouswave.com/whaler/reference/DSC_Datagrams.html - -- [[ANON]] - Anonymous commentator(s) are persons who have volunteered information - about the NMEA standard(s) but do not wish to be identified. - -- [[[NORWAY]]] - "Etterretninger for sjøfarende" Notoces for Mariners, see p26 - http://kartverket.no/efs-documents/editions/2015/efs01-2015.pdf diff --git a/www/client-howto.adoc b/www/client-howto.adoc new file mode 100644 index 00000000..96890035 --- /dev/null +++ b/www/client-howto.adoc @@ -0,0 +1,642 @@ += GPSD Client HOWTO = +:description: This document is a guide to interfacing client applications with GPSD. +:keywords: time, GPSD, NTP, time, precision, 1PPS, PPS, stratum, jitter +Eric S. Raymond +v1.19, Jul 2015 + +== Introduction == + +This document is a guide to interfacing client applications with GPSD. +It surveys the available bindings and their use cases. It also explains +some sharp edges in the client API which, unfortunately, are fundamental +results of the way GPS sensor devices operate, and suggests tactics +for avoiding being cut. + +== Sensor behavior matters == + +GPSD handles two main kinds of sensors: GPS receivers and AIS +receivers. It has rudimentary support for some other kinds of +specialized geolocation-related sensors as well, notably compass and +yaw/pitch/roll, but those sensors are usually combined with GPS/AIS +receivers and behave like them. + +In an ideal world, GPS/AIS sensors would be oracles that you could +poll at any time to get clean data. But despite the existence of some +vendor-specific query and control strings on some devices, a GPS/AIS +sensor is not a synchronous device you can query for specified data +and count on getting a response back from in a fixed period of time. +It gets radio data on its own schedule (usually once per second for a +GPS), and emits the reports it feels like reporting asynchronously +with variable lag during the following second. *If* it supports query +strings, reports from these are intermixed with the regular +reports, and usually scheduled at a lower priority (often with a lag +of more than a second). + +A GPS/AIS receiver, or any sensor that behaves like one, is in effect +a datagram emitter similar to a UDP data source; you get no guarantees +about sequence or timing at finer resolution than "TPV roughly once +per second" (or whatever the main type of report and report interval +is). + +The only way to simulate synchronous querying of such a sensor is to +have an agent between you and it that caches the data coming out of +the device; you can then query the agent and expect a reasonably +synchronous response from the cache (we support this for +GPSes). However, note that this doesn't work for a freshly opened +device - there's no cached data. + +Consider what this implies for GPses, in particular: + +* You can't actually poll them. They report to you over a serial + (RS232 or USB-serial) interface at a fixed interval, usually once + per second. + +* They don't always have a fix to report, because they can only + get one when they have satellite lock. + +* They may fail to have satellite lock when your skyview is poor. + If you are moving through uneven terrain or anywhere with trees + or buildings, your skyview can degrade in an instant. + +* They may also fail to have lock because they're initially powering + on (cold start), or waking from a power-conserving sleep mode (warm + start). While most modern GPSes with a good skyview can get + satellite lock in 30 seconds from a warm start, a GPS that has + been off for a while can take 15 minutes or more to acquire lock + +Time to fix after a power-on matters because in many use cases for +GPSes they're running off a battery, and you can't afford to keep them +powered when you don't actually need location data. This is why GPS +sensors are sometimes designed to go to a low-power mode when you close +the serial port they're attached to. + +AIS receivers have a simpler set of constraints. They report +navigational and ID information from any AIS transmitter in line of +sight; there are no skyview issues, and they're ready instantly when +powered up. Furthermore, they're not normally battery constrained. +However, you don't poll them either; they receive information +packets over the air and ship them to you at unpredictable intervals +over a serial port. + +The design of the GPSD reporting protocol surrenders to reality. Its data +packets translate the GPS's stream of datagrams into +device-type-independent datagrams, but it can't impose timing and +sequencing regularities on them that the underlying device doesn't +already obey. + +== What GPSD does, and what it cannot do == + +GPSD solves some of the problems with GPS/AIS sensors. First: +multiplexing; it allows multiple applications to get sensor data +without having to contend for a single serial device. Second: +coping with the hideous gallimaufry of badly-designed protocols these +devices use -- regardless of device type, you will get data in a single +well-documented format. Third: on operating systems with a hotplug +facility (like Linux udev), GPSD will handle all the device +management as USB devices are plugged in and unplugged. + +What GPSD can't do is pull fix data out of thin air when your +device hasn't reported any. Nor is it a magic power supply, +so its device management has to be designed around keeping the +attached sensors open only when a client application actually +needs a fix. + +As you'll see, these constraints explain most of the design of the GPSD +wire protocol, and of the library APIs your client application +will be using. + +== How the GPSD wire protocol works == + +While GPSD project ships several library bindings that will hide the +details of the wire protocol from you, you'll understand the library APIs +better by knowing what a wire-protocol session looks like. After +reading this section, you can forget the details about commands and +responses and attributes as long as you hold on to the basic +logical flow of a session. + +Your client library's open function is going to connect a socket to +port 2947 on the host your sensors are attached to, usually +localhost. On connection, the gpsd daemon will ship a banner that +looks something like this: + +----------------------------------------------------------------------------- +{"class":"VERSION","release":"2.93","rev":"2010-03-30T12:18:17", + "proto_major":3,"proto_minor":2} +----------------------------------------------------------------------------- + +There's nothing mysterious here. Your server daemon is identifying +itself with information that may allow a client library to work +around bugs or potential incompatibilities produced by upgrades. + +To get data from the attached sensors, you need to explicitly tell the +daemon you want it. (Remember that it's trying to minimize the amount +of time the devices are held open and in a fully powered state.) You +do this by issuing a WATCH command: + +----------------------------------------------------------------------------- +?WATCH={"enable":true,"json":true} +----------------------------------------------------------------------------- + +This tells the daemon to watch all devices and to issue reports in +JSON. It can ship some other protocols as well (notably, NMEA 0183) +but JSON is the most capable and usually what you want. + +A side effect of the WATCH command is that the daemon will ship you +back some information on available devices. + +----------------------------------------------------------------------------- +{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyUSB0", + "activated":1269959537.20,"native":0,"bps":4800,"parity":"N", + "stopbits":1,"cycle":1.00}]} +{"class":"WATCH","enable":true,"json":true,"nmea":false,"raw":0, + "scaled":false,"timing":false,"pps":false} +----------------------------------------------------------------------------- + +The DEVICES response tells you what devices are available to the +daemon; this list is maintained in a way you as the application +designer don't have to care about. The WATCH response will +immediately follow and tells you what all your watch request settings +are. + +Up to this point, nothing has been dependent on the state of the +sensors. At this time, it may well be that none of those devices is +fully powered up yet. In fact, they won't be, unless another +GPSD-enabled application is already watching when you open your +connection. If that's the case, you will start seeing data +immediately. + +For now, though, let's go back to the case where gpsd has to fire up +the sensors. After issuing the WATCH response, the daemon opens all of +them and watches for incoming packets that it can recognize. *After +a variable delay*, it will ship a notification that looks something +like this: + +----------------------------------------------------------------------------- +{"class":"DEVICE","path":"/dev/ttyUSB0","activated":1269960793.97, + "driver":"SiRF binary","native":1,"bps":4800, + "parity":"N","stopbits":1,"cycle":1.00} +----------------------------------------------------------------------------- + +This is the daemon telling you that it has recognized a SiRF binary +GPS on /dev/ttyUSB0 shipping report packets at 4800 bits per second. +This notification is not delayed by the time it takes to achieve +satellite lock; the GPS will cheerfully ship packets before that. But +it will be delayed by the time required for the daemon to sync up with +the GPS. + +The GPSD daemon is designed so it doesn't have to know anything about the +sensor in advance - not which of a dozen reporting protocols it uses, +and not even the baud rate of the serial device. The reason for this +agnosticism is so the daemon can adapt properly to anything a hotplug +event night throw at it. If you unplug your GPS while your +application is running, and then plug one one of a different type, the +daemon will cope. Your application won't know the difference unless +you have told it to notice device types. + +You can even start your application, have it issue a WATCH, realize +you forgot to plug in a GPS, and do that. The hotplug event will +tell gpsd, which will add the new device to the watched-devices list +of every client that has issued a ?WATCH. + +In order to make this work, gpsd has a packet sniffer inside it that +does autobauding and packet-protocol detection. Normally the packet +sniffer will achieve sync in well under a second (my measured times +range from 0.10 to 0.53 sec at 4800bps), but it can take longer if +your serial traffic is degraded by dodgy cables or electrical noise, +or if the GPS is configured to run at an unusual speed/parity/stopbit +configuration. + +The real point here is that the delay is *variable*. The client +library, and your application, can't assume a neat lockstep of +request and instant response. + +Once you do get your device(s) synced, things become more predictable. +The sensor will start shipping fix reports at a constant interval, +usually every second, and the daemon will massage them into JSON and +pass them up the client to your application. + +However, until the sensor achieves satellite lock, those fixes will be +"mode 1" - no valid data (mode 2 is a 2D fix, mode 3 is a 3D fix). +Here's what that looks like: + +----------------------------------------------------------------------------- +{"class":"TPV","device":"/dev/ttyUSB0", + "time":"2010-04-30T11:47:43.28Z","ept":0.005,"mode":1} +----------------------------------------------------------------------------- + +Occasionally you'll get another kind of sentence, SKY, that reports a +satellite skyview. But TPV is the important one. Here's what it +looks like when the sensor has a fix to report: + +----------------------------------------------------------------------------- +{"class":"TPV","time":"2010-04-30T11:48:20.10Z","ept":0.005, + "lat":46.498204497,"lon":7.568061439,"alt":1327.689, + "epx":15.319,"epy":17.054,"epv":124.484,"track":10.3797, + "speed":0.091,"climb":-0.085,"eps":34.11,"mode":3} +----------------------------------------------------------------------------- + +Note the "mode":3 at the end. This is how you tell that the GPS is +reporting a full 3D fix with altitude. + +If you have an AIS receiver attached, it too will have been opened +and autobauded and protocol-sniffed after your WATCH. The stream of +JSON objects will then include things like this: + +----------------------------------------------------------------------------- +{"class":"AIS","type":5,"repeat":0,"mmsi":351759000,"scaled":true, + "imo":9134270,"ais_version":0,"callsign":"3FOF8", + "shipname":"EVER DIADEM", + "shiptype":"Cargo - all ships of this type", + "to_bow":225, + "to_stern":70,"to_port":1,"to_starboard":31,"draught":12.2, + "epfd":"GPS","eta":"05-15T14:00Z", + "destination":"NEW YORK","dte":0} +----------------------------------------------------------------------------- + +When your application shuts down, it can cancel its watch: + +----------------------------------------------------------------------------- +?WATCH={"enable":false} +----------------------------------------------------------------------------- + +This will enable the daemon to close devices and conserve +power. Supposing you don't do this, the daemon will time out devices +with no listeners, so canceling your watch is not strictly necessary. +But it is good manners. + +Another way to use the daemon is with the ?POLL command To do this, issue + +----------------------------------------------------------------------------- +?WATCH={"enable":true} +----------------------------------------------------------------------------- + +This activates all devices without enabling streaming of reports. You +can then say "?POLL;" to poll gpsd's recorded data. + +----------------------------------------------------------------------------- +?POLL; +{"class":"POLL","time":"2012-04-05T15:00:01.501Z","active":1, + "tpv":[{"class":"TPV","device":"/dev/ttyUSB0","mode":3,"time":"2012-04-05T15:00:00.000Z","ept":0.005,"lat":40.035083522,"lon":-75.519982905,"alt":166.145,"epx":9.125,"epy":17.778,"epv":34.134,"track":0.0000,"speed":0.000,"climb":0.000,"eps":36.61}],"gst":[{"class":"GST","device":"/dev/ttyUSB0","time":"1970-01-01T00:00:00.000Z","rms":0.000,"major":0.000,"minor":0.000,"orient":0.000,"lat":0.000,"lon":0.000,"alt":0.000}], + "sky":[{"class":"SKY","device":"/dev/ttyUSB0","time":"2012-04-05T15:00:00.000Z","xdop":0.61,"ydop":1.19,"vdop":1.48,"tdop":1.14,"hdop":1.40,"gdop":2.30,"pdop":1.99,"satellites":[{"PRN":26,"el":15,"az":49,"ss":29,"used":true},{"PRN":18,"el":62,"az":315,"ss":31,"used":true},{"PRN":15,"el":60,"az":43,"ss":44,"used":true},{"PRN":21,"el":71,"az":237,"ss":0,"used":false},{"PRN":27,"el":52,"az":94,"ss":40,"used":true},{"PRN":9,"el":48,"az":136,"ss":33,"used":true},{"PRN":22,"el":21,"az":291,"ss":36,"used":true},{"PRN":3,"el":8,"az":303,"ss":25,"used":true}]}]} +----------------------------------------------------------------------------- + +This interface is intended for use with applications like CGI scripts +that cannot wait on output from the daemon but must poke it into responding. + +If you're a clever sort, you're already wondering what the daemon does +if the application at the other end of the client socket doesn't read data +out of it as fast as gpsd is shipping it upwards. And the answer is +this: eventually the socket buffer fills up, a write from the daemon +throws an error, and the daemon shuts down that client socket. + +From the point of view of the application, it reads all the buffered +data and then gets a read return indicating the socket shutdown. We'll +return to this in the discussion of client libraries, but the thing +for you to know right now is that this edge case is actually quite +difficult to fall afoul of. Total data volume on these sockets is not +high. As long as your application checks for and reads socket data no +less often than once a second, you won't -- and a second is a *lot* of +time in which to come back around your main loop. + +== Interfacing from the client side == + +The gpsd daemon exports data in three different ways: via a sockets +interface, via DBUS broadcasts, and via a shared-memory interface, +It is possible one or more of these may be configured out in your +installation. + +=== The sockets interface === + +The GPSD project provides client-side libraries in C, C++, and Python +that exercise the sockets export. A Perl module is separately +available from CPAN. While the details of these libraries vary, they +all have the same two purposes and the same limitations. + +One purpose of the libraries is to handle the details of unpacking +JSON-based wire-protocol objects into whatever native structure/record +feature your application language has. This is particularly important +in the C and C++ libraries, because those languages don't have +good native support for JSON. + +Another purpose is to hide the details of the wire protocol from the +application. This gives the GPSD developers room to improve extend +the protocol without breaking every client application. Depend +on wire-protocol details only at your own risk! + +The limitations the libraries have to cope with are the nature of +the data flow from the sensors, and the simple fact that they're +not necessarily delivering fixes at any given time. + +For details of the libraries' APIs, see their reference +documentation; the objective of the rest of this section is to teach +you the general model of client-side interfacing that they all have to +follow because of the way the daemon works. + +Each library has the following entry points: + +* Open a session socket to the daemon. Named something like "open()". + +* Set watch policy. Named something like "stream()" + +* Send wire-protocol commands to the daemon. Deprecated; makes your + code dependent on the wire protocol. There is no longer a real + use case for this entry point; if you think you need no use it, + you have probably failed to understand the rest of the interface. + +* Blocking check to see if data from the daemon is waiting. Named + something like "waiting()" and taking a wait timeout as argument. + Note that choosing a wait timeout of less than twice the cycle time + of your device will be hazardous, as the receiver will probably not + supply input often enough to prevent a spurious error indication. + For the typical 1-second cycle time of GPSes this implies a minimum + 2-second timeout. + +* Blocking read for data from the daemon. Named something like "read()" + (this was "poll()" in older versions). + +* Close the session socket. Named something like "close()". + +* Enable debugging trace messages + +The fact that the data-waiting check and the read both block means +that, if your application has to deal with other input sources than +the GPS, you will probably have to isolate the read loop in a thread with +a mutex lock on the gps_data structure. + +Here is a complete table of the binding entry points: + +.Entry points in client bindings +[frame="topbot",options="header"] +|======================================================================== +|C |C++ |Python | +Function +|gps_open() |gpsmm.gpsmm() |gps.\_\_init__() | +In OO languages the client class initializer opens the daemon socket. +|gps_send() |gpsmm.send() |gps.send() | +Send wire-protocol commands to the daemon. Deprecated and unstable. +|gps_stream() |gpsmm.stream() |gps.stream() | +Set watch policy. What you should use instead of send(). +|gps_waiting() |gpsmm.waiting() |gps.waiting() | +Blocking check with timeout to see if input is waiting. +|gps_read() |gpsmm.read() |gps.read() | +Blocking read for data from the daemon. +|gps_unpack() | |gps.unpack() | +Parse JSON from a specified buffer into a session structure +|gps_close() |gpsmm.~gpsmm() |gps.close() | +Close the daemon socket and end the session. +|gps_data() |gpsmm.data() |gps.data() | +Get the contents of the client buffer. +|gps_enable_debug() |gpsmm_enable_debug() | | +Enable debug tracing. Only useful for GPSD developers. +|gps_clear_fix() |gpsmm.clear_fix() | | +Clear the contents of the fix structure. +|======================================================================== + +The tricky part is interpreting what you get from the blocking +read. The reason it's tricky is that you're not guaranteed that +every read will pick up exactly one complete JSON object from the +daemon. It may grab one response object, or more than one, or +part of one, or one or more followed by a fragment. + +What the library does on each read is this: get what it can from the +socket, append that to a private buffer, and then consume as many JSON +objects from the front of the buffer as it can. Any incomplete JSON +is left in the private buffer to be completed and unpacked on a later +go-round. + +In C, the library "consumes" a JSON object by unpacking its content +into a blackboard structure passed to the read entry point by +address. The structure contains a state-flag mask that you can (and +should!) check so you'll know which parts of the structure contain +valid data. It is safe to do nothing unless the PACKET_SET mask bit +is on, which is the library's way of telling you that at least one +complete JSON response has arrived since the last read. + +Data may accumulate on the blackboard over multiple reads, +with new TPV reports overwriting old ones; it is guaranteed that +overwrites are not partial. Expect this pattern to be replicated +in any compiled language with only fixed-extent structures. + +In Python and Perl the read entry point returns an object containing +accumulated data. The state-flag mask is still useful for telling you +which parts contain data, and there is still a PACKET_SET bit. Expect +this pattern to be replicated in other dynamic OO languages when we +support them. + +The C++ binding is a very thin wrapper around the C. You get back an +object, but it's just a reference to the C blackboard structure. There's +no unpack() method because it doesn't fit the gpsmm object's RAII model. + +All bindings will throw a recognizable error from the read entry +point when the socket is closed from the daemon side. + +[WARNING] +The timing of your read loop is important. When it has satellite lock, +the daemon will be writing into its end of the socket once per +whatever the normal reporting-cycle time of your device is - for a GPS +normally one peer second. *You must poll the socket more often that +that.* + +If necessary, spawn a worker thread to do this, mutex-locking the +structure where it outs the reports. If you don't do this, data +will back up in your socket buffers and position reports will be +more and more delayed until the socket FIFO fills, at which point the +daemon will conclude the client has died and drop the connection. + +AIVDM clients have a longer maximum allowable poll interval, but a +problem of a different kind. you have the problem that later sentences +of (say) Type 1 don't obsolete the data in earlier ones. This is a +problem, because the library is designed so that read calls pull any +JSON reports waiting from the daemon and interpret them all. + +To avoid losing data, you want to poll the daemon more often than once +per two seconds (that being the minimum transmission period for the +most frequently shipped sentences, Type 1/2/3). That way the read +buffer will never contain both a message and a later message of the +same type that steps on it. + +=== Shared-memory interface === + +Whenever gpsd recognizes a packet from any attached device, it writes +the accumulated state from that device to a shared memory segment. The +C and C++ client libraries shipped with GPSD can read this segment. + +The API for reading the segment uses the same gps_open(), gps_read() +and gps_close() entry points as the sockets interface. To enable using +shared memory instead, it is only necessary to use the macro constant +GPSD_SHARED_MEMORY as the host argument of gps_open(). + +The gps_stream(), gps_send(), gps_waiting(), and gps_data() entry +points are not available with this interface. You cannot set a device +filter on it. You will not get device activation or deactivation +notices through it. And, of course, it is only good for local and not +networked access. Its main advantage is that it is very fast and +lightweight, especially suitable for use in low-power embedded +deployments with a single device on a fixed port and the sockets +interface configured out. + +Under the shared-memory interface, gps_read() after a successful +gps_open() will always return with data; its return is the size of a +struct gps_data_t in bytes. The 'gps_fd' member of the struct gpsdata +instance handed to you will always be -1. The PACKET_SET flag will +always be asserted. The other flag bits in the 'set' member will tell +you what data is updated in the instance, just as in the sockets +interface. + +The shared-memory interface is not yet available from Python. + +=== D-Bus broadcasts === + +If your system supports D-Bus, gpsd broadcasts a signal with path /org/gpsd, +interface "org.gpsd", and name "fix" whenever it received a position +report from any device attached to it. See the gpsd(8) manual page for +details of the binary payload layout. + +== C Examples == + +The source distribution includes two example clients in C; +gpxlogger.c and cgps.c. + +gpxlogger.c illustrates the simplest possible program flow; open, +followed by stream, followed by the library main loop. + +cgps.c shows what an interactive application using the library and +also hw processing user commands works. Note the use of the curses +nodelay function to ensure that wgetch() does not block the GPS +polling loop. + +== C++ examples == + +The following code skeleton implements a C++ client: + +---------------------------------------------------------------------- + +int main(void) +{ + gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT); + + if (gps_rec.stream(WATCH_ENABLE|WATCH_JSON) == NULL) { + cerr << "No GPSD running.\n"; + return 1; + } + + for (;;) { + struct gps_data_t* newdata; + + if (!gps_rec.waiting(50000000)) + continue; + + if ((newdata = gps_rec.read()) == NULL) { + cerr << "Read error.\n"; + return 1; + } else { + PROCESS(newdata); + } + } + return 0; +} + +---------------------------------------------------------------------- + +Note the absence of explicit open and close methods. The object +interface is designed on the RAII (Resource Acquisition Is +Initialization) model; you close it by deallocating it. + +Look at test_gpsmm.cpp in the distribution for a full example. + +== Python examples == + +There's a very simple Python example analogous to gpxlogger attached +to the source code for the gps.py library. + +The heart of it is this code: + +----------------------------------------------------------------------------- + session = gps(**opts) + session.stream(WATCH_ENABLE|WATCH_NEWSTYLE) + for report in session: + print report +----------------------------------------------------------------------------- + +If you need to intersperse other processing in a main event loop, +like this: + +---------------------------------------------------------------------- + +session = gps(mode=WATCH_ENABLE) +try: + while True: + # Do stuff + report = session.next() + # Check report class for 'DEVICE' messages from gpsd. If + # we're expecting messages from multiple devices we should + # inspect the message to determine which device + # has just become available. But if we're just listening + # to a single device, this may do. + if report['class'] == 'DEVICE': + # Clean up our current connection. + session.close() + # Tell gpsd we're ready to receive messages. + session = gps(mode=WATCH_ENABLE) + # Do more stuff +except StopIteration: + print "GPSD has terminated" + +---------------------------------------------------------------------- + +Each call to the iterator yields a report structure until the daemon +terminates, at which point the iterator next() method will raise +StopIteration and the loop will terminate. + +The report object returned by next() can be accessed either as a dictionary +or as an object. As a dictionary, it is the raw contents of the last +JSON response re-encoded in plain ASCII. For convenience, you may +also access it as an object with members for each attribute in the +dictionary. It is especially useful to know that the object will +always have a "class" member giving the response type (TPV, SKY, +DEVICE, etc.) as a string. + +For more interesting examples integrated with X and GTK, see xgps and +xgpsspeed. + +== Other Client Bindings == + +There are a couple of client bindings for GPSD that are maintained +separately from the GPSD distribution. We don't try to document their +APIs here, but just provide pointers to them. + +== Java == + +There is a Java binding, described at http://gpsd4java.forge.hoegergroup.de/ +This binding is available at maven central. See that web page for how +to use it in a maven build. + +== Perl == + +There's a Perl client library at http://search.cpan.org/dist/Net-GPSD3/ + +== Backward Incompatibility and Future Changes == + +The C/C++ binding makes available two preprocessor symbols, +GPSD_API_MAJOR_VERSION and GPSD_API_MINOR_VERSION, in gps.h. +The Python module has corresponding symbols. + +In major versions before 5: + +* gps_open() didn't take a third argument; instead, it returned malloc storage. + +* The 'read()' method in various bindings was named 'poll()', blocked + waiting for input, and had a different return convention. The name + 'poll()' will at some point be reintroduced as an interface to the + wire-protocol POLL command. + +* Clients needed to define a hook for client-side logging if they + didn't want code in netlib.c and libgps_core.c to occasionally send + messages to stderr. This requirement is now gone. + +* There was a set_raw_hook() method in the C and Python bindings, now gone. + C clients should call gps_data(); the buffer is available directly in Python, + both as str (response) and bytes (bresponse). The distinction matters + in Python 3. + +//end diff --git a/www/client-howto.txt b/www/client-howto.txt deleted file mode 100644 index 96890035..00000000 --- a/www/client-howto.txt +++ /dev/null @@ -1,642 +0,0 @@ -= GPSD Client HOWTO = -:description: This document is a guide to interfacing client applications with GPSD. -:keywords: time, GPSD, NTP, time, precision, 1PPS, PPS, stratum, jitter -Eric S. Raymond -v1.19, Jul 2015 - -== Introduction == - -This document is a guide to interfacing client applications with GPSD. -It surveys the available bindings and their use cases. It also explains -some sharp edges in the client API which, unfortunately, are fundamental -results of the way GPS sensor devices operate, and suggests tactics -for avoiding being cut. - -== Sensor behavior matters == - -GPSD handles two main kinds of sensors: GPS receivers and AIS -receivers. It has rudimentary support for some other kinds of -specialized geolocation-related sensors as well, notably compass and -yaw/pitch/roll, but those sensors are usually combined with GPS/AIS -receivers and behave like them. - -In an ideal world, GPS/AIS sensors would be oracles that you could -poll at any time to get clean data. But despite the existence of some -vendor-specific query and control strings on some devices, a GPS/AIS -sensor is not a synchronous device you can query for specified data -and count on getting a response back from in a fixed period of time. -It gets radio data on its own schedule (usually once per second for a -GPS), and emits the reports it feels like reporting asynchronously -with variable lag during the following second. *If* it supports query -strings, reports from these are intermixed with the regular -reports, and usually scheduled at a lower priority (often with a lag -of more than a second). - -A GPS/AIS receiver, or any sensor that behaves like one, is in effect -a datagram emitter similar to a UDP data source; you get no guarantees -about sequence or timing at finer resolution than "TPV roughly once -per second" (or whatever the main type of report and report interval -is). - -The only way to simulate synchronous querying of such a sensor is to -have an agent between you and it that caches the data coming out of -the device; you can then query the agent and expect a reasonably -synchronous response from the cache (we support this for -GPSes). However, note that this doesn't work for a freshly opened -device - there's no cached data. - -Consider what this implies for GPses, in particular: - -* You can't actually poll them. They report to you over a serial - (RS232 or USB-serial) interface at a fixed interval, usually once - per second. - -* They don't always have a fix to report, because they can only - get one when they have satellite lock. - -* They may fail to have satellite lock when your skyview is poor. - If you are moving through uneven terrain or anywhere with trees - or buildings, your skyview can degrade in an instant. - -* They may also fail to have lock because they're initially powering - on (cold start), or waking from a power-conserving sleep mode (warm - start). While most modern GPSes with a good skyview can get - satellite lock in 30 seconds from a warm start, a GPS that has - been off for a while can take 15 minutes or more to acquire lock - -Time to fix after a power-on matters because in many use cases for -GPSes they're running off a battery, and you can't afford to keep them -powered when you don't actually need location data. This is why GPS -sensors are sometimes designed to go to a low-power mode when you close -the serial port they're attached to. - -AIS receivers have a simpler set of constraints. They report -navigational and ID information from any AIS transmitter in line of -sight; there are no skyview issues, and they're ready instantly when -powered up. Furthermore, they're not normally battery constrained. -However, you don't poll them either; they receive information -packets over the air and ship them to you at unpredictable intervals -over a serial port. - -The design of the GPSD reporting protocol surrenders to reality. Its data -packets translate the GPS's stream of datagrams into -device-type-independent datagrams, but it can't impose timing and -sequencing regularities on them that the underlying device doesn't -already obey. - -== What GPSD does, and what it cannot do == - -GPSD solves some of the problems with GPS/AIS sensors. First: -multiplexing; it allows multiple applications to get sensor data -without having to contend for a single serial device. Second: -coping with the hideous gallimaufry of badly-designed protocols these -devices use -- regardless of device type, you will get data in a single -well-documented format. Third: on operating systems with a hotplug -facility (like Linux udev), GPSD will handle all the device -management as USB devices are plugged in and unplugged. - -What GPSD can't do is pull fix data out of thin air when your -device hasn't reported any. Nor is it a magic power supply, -so its device management has to be designed around keeping the -attached sensors open only when a client application actually -needs a fix. - -As you'll see, these constraints explain most of the design of the GPSD -wire protocol, and of the library APIs your client application -will be using. - -== How the GPSD wire protocol works == - -While GPSD project ships several library bindings that will hide the -details of the wire protocol from you, you'll understand the library APIs -better by knowing what a wire-protocol session looks like. After -reading this section, you can forget the details about commands and -responses and attributes as long as you hold on to the basic -logical flow of a session. - -Your client library's open function is going to connect a socket to -port 2947 on the host your sensors are attached to, usually -localhost. On connection, the gpsd daemon will ship a banner that -looks something like this: - ------------------------------------------------------------------------------ -{"class":"VERSION","release":"2.93","rev":"2010-03-30T12:18:17", - "proto_major":3,"proto_minor":2} ------------------------------------------------------------------------------ - -There's nothing mysterious here. Your server daemon is identifying -itself with information that may allow a client library to work -around bugs or potential incompatibilities produced by upgrades. - -To get data from the attached sensors, you need to explicitly tell the -daemon you want it. (Remember that it's trying to minimize the amount -of time the devices are held open and in a fully powered state.) You -do this by issuing a WATCH command: - ------------------------------------------------------------------------------ -?WATCH={"enable":true,"json":true} ------------------------------------------------------------------------------ - -This tells the daemon to watch all devices and to issue reports in -JSON. It can ship some other protocols as well (notably, NMEA 0183) -but JSON is the most capable and usually what you want. - -A side effect of the WATCH command is that the daemon will ship you -back some information on available devices. - ------------------------------------------------------------------------------ -{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyUSB0", - "activated":1269959537.20,"native":0,"bps":4800,"parity":"N", - "stopbits":1,"cycle":1.00}]} -{"class":"WATCH","enable":true,"json":true,"nmea":false,"raw":0, - "scaled":false,"timing":false,"pps":false} ------------------------------------------------------------------------------ - -The DEVICES response tells you what devices are available to the -daemon; this list is maintained in a way you as the application -designer don't have to care about. The WATCH response will -immediately follow and tells you what all your watch request settings -are. - -Up to this point, nothing has been dependent on the state of the -sensors. At this time, it may well be that none of those devices is -fully powered up yet. In fact, they won't be, unless another -GPSD-enabled application is already watching when you open your -connection. If that's the case, you will start seeing data -immediately. - -For now, though, let's go back to the case where gpsd has to fire up -the sensors. After issuing the WATCH response, the daemon opens all of -them and watches for incoming packets that it can recognize. *After -a variable delay*, it will ship a notification that looks something -like this: - ------------------------------------------------------------------------------ -{"class":"DEVICE","path":"/dev/ttyUSB0","activated":1269960793.97, - "driver":"SiRF binary","native":1,"bps":4800, - "parity":"N","stopbits":1,"cycle":1.00} ------------------------------------------------------------------------------ - -This is the daemon telling you that it has recognized a SiRF binary -GPS on /dev/ttyUSB0 shipping report packets at 4800 bits per second. -This notification is not delayed by the time it takes to achieve -satellite lock; the GPS will cheerfully ship packets before that. But -it will be delayed by the time required for the daemon to sync up with -the GPS. - -The GPSD daemon is designed so it doesn't have to know anything about the -sensor in advance - not which of a dozen reporting protocols it uses, -and not even the baud rate of the serial device. The reason for this -agnosticism is so the daemon can adapt properly to anything a hotplug -event night throw at it. If you unplug your GPS while your -application is running, and then plug one one of a different type, the -daemon will cope. Your application won't know the difference unless -you have told it to notice device types. - -You can even start your application, have it issue a WATCH, realize -you forgot to plug in a GPS, and do that. The hotplug event will -tell gpsd, which will add the new device to the watched-devices list -of every client that has issued a ?WATCH. - -In order to make this work, gpsd has a packet sniffer inside it that -does autobauding and packet-protocol detection. Normally the packet -sniffer will achieve sync in well under a second (my measured times -range from 0.10 to 0.53 sec at 4800bps), but it can take longer if -your serial traffic is degraded by dodgy cables or electrical noise, -or if the GPS is configured to run at an unusual speed/parity/stopbit -configuration. - -The real point here is that the delay is *variable*. The client -library, and your application, can't assume a neat lockstep of -request and instant response. - -Once you do get your device(s) synced, things become more predictable. -The sensor will start shipping fix reports at a constant interval, -usually every second, and the daemon will massage them into JSON and -pass them up the client to your application. - -However, until the sensor achieves satellite lock, those fixes will be -"mode 1" - no valid data (mode 2 is a 2D fix, mode 3 is a 3D fix). -Here's what that looks like: - ------------------------------------------------------------------------------ -{"class":"TPV","device":"/dev/ttyUSB0", - "time":"2010-04-30T11:47:43.28Z","ept":0.005,"mode":1} ------------------------------------------------------------------------------ - -Occasionally you'll get another kind of sentence, SKY, that reports a -satellite skyview. But TPV is the important one. Here's what it -looks like when the sensor has a fix to report: - ------------------------------------------------------------------------------ -{"class":"TPV","time":"2010-04-30T11:48:20.10Z","ept":0.005, - "lat":46.498204497,"lon":7.568061439,"alt":1327.689, - "epx":15.319,"epy":17.054,"epv":124.484,"track":10.3797, - "speed":0.091,"climb":-0.085,"eps":34.11,"mode":3} ------------------------------------------------------------------------------ - -Note the "mode":3 at the end. This is how you tell that the GPS is -reporting a full 3D fix with altitude. - -If you have an AIS receiver attached, it too will have been opened -and autobauded and protocol-sniffed after your WATCH. The stream of -JSON objects will then include things like this: - ------------------------------------------------------------------------------ -{"class":"AIS","type":5,"repeat":0,"mmsi":351759000,"scaled":true, - "imo":9134270,"ais_version":0,"callsign":"3FOF8", - "shipname":"EVER DIADEM", - "shiptype":"Cargo - all ships of this type", - "to_bow":225, - "to_stern":70,"to_port":1,"to_starboard":31,"draught":12.2, - "epfd":"GPS","eta":"05-15T14:00Z", - "destination":"NEW YORK","dte":0} ------------------------------------------------------------------------------ - -When your application shuts down, it can cancel its watch: - ------------------------------------------------------------------------------ -?WATCH={"enable":false} ------------------------------------------------------------------------------ - -This will enable the daemon to close devices and conserve -power. Supposing you don't do this, the daemon will time out devices -with no listeners, so canceling your watch is not strictly necessary. -But it is good manners. - -Another way to use the daemon is with the ?POLL command To do this, issue - ------------------------------------------------------------------------------ -?WATCH={"enable":true} ------------------------------------------------------------------------------ - -This activates all devices without enabling streaming of reports. You -can then say "?POLL;" to poll gpsd's recorded data. - ------------------------------------------------------------------------------ -?POLL; -{"class":"POLL","time":"2012-04-05T15:00:01.501Z","active":1, - "tpv":[{"class":"TPV","device":"/dev/ttyUSB0","mode":3,"time":"2012-04-05T15:00:00.000Z","ept":0.005,"lat":40.035083522,"lon":-75.519982905,"alt":166.145,"epx":9.125,"epy":17.778,"epv":34.134,"track":0.0000,"speed":0.000,"climb":0.000,"eps":36.61}],"gst":[{"class":"GST","device":"/dev/ttyUSB0","time":"1970-01-01T00:00:00.000Z","rms":0.000,"major":0.000,"minor":0.000,"orient":0.000,"lat":0.000,"lon":0.000,"alt":0.000}], - "sky":[{"class":"SKY","device":"/dev/ttyUSB0","time":"2012-04-05T15:00:00.000Z","xdop":0.61,"ydop":1.19,"vdop":1.48,"tdop":1.14,"hdop":1.40,"gdop":2.30,"pdop":1.99,"satellites":[{"PRN":26,"el":15,"az":49,"ss":29,"used":true},{"PRN":18,"el":62,"az":315,"ss":31,"used":true},{"PRN":15,"el":60,"az":43,"ss":44,"used":true},{"PRN":21,"el":71,"az":237,"ss":0,"used":false},{"PRN":27,"el":52,"az":94,"ss":40,"used":true},{"PRN":9,"el":48,"az":136,"ss":33,"used":true},{"PRN":22,"el":21,"az":291,"ss":36,"used":true},{"PRN":3,"el":8,"az":303,"ss":25,"used":true}]}]} ------------------------------------------------------------------------------ - -This interface is intended for use with applications like CGI scripts -that cannot wait on output from the daemon but must poke it into responding. - -If you're a clever sort, you're already wondering what the daemon does -if the application at the other end of the client socket doesn't read data -out of it as fast as gpsd is shipping it upwards. And the answer is -this: eventually the socket buffer fills up, a write from the daemon -throws an error, and the daemon shuts down that client socket. - -From the point of view of the application, it reads all the buffered -data and then gets a read return indicating the socket shutdown. We'll -return to this in the discussion of client libraries, but the thing -for you to know right now is that this edge case is actually quite -difficult to fall afoul of. Total data volume on these sockets is not -high. As long as your application checks for and reads socket data no -less often than once a second, you won't -- and a second is a *lot* of -time in which to come back around your main loop. - -== Interfacing from the client side == - -The gpsd daemon exports data in three different ways: via a sockets -interface, via DBUS broadcasts, and via a shared-memory interface, -It is possible one or more of these may be configured out in your -installation. - -=== The sockets interface === - -The GPSD project provides client-side libraries in C, C++, and Python -that exercise the sockets export. A Perl module is separately -available from CPAN. While the details of these libraries vary, they -all have the same two purposes and the same limitations. - -One purpose of the libraries is to handle the details of unpacking -JSON-based wire-protocol objects into whatever native structure/record -feature your application language has. This is particularly important -in the C and C++ libraries, because those languages don't have -good native support for JSON. - -Another purpose is to hide the details of the wire protocol from the -application. This gives the GPSD developers room to improve extend -the protocol without breaking every client application. Depend -on wire-protocol details only at your own risk! - -The limitations the libraries have to cope with are the nature of -the data flow from the sensors, and the simple fact that they're -not necessarily delivering fixes at any given time. - -For details of the libraries' APIs, see their reference -documentation; the objective of the rest of this section is to teach -you the general model of client-side interfacing that they all have to -follow because of the way the daemon works. - -Each library has the following entry points: - -* Open a session socket to the daemon. Named something like "open()". - -* Set watch policy. Named something like "stream()" - -* Send wire-protocol commands to the daemon. Deprecated; makes your - code dependent on the wire protocol. There is no longer a real - use case for this entry point; if you think you need no use it, - you have probably failed to understand the rest of the interface. - -* Blocking check to see if data from the daemon is waiting. Named - something like "waiting()" and taking a wait timeout as argument. - Note that choosing a wait timeout of less than twice the cycle time - of your device will be hazardous, as the receiver will probably not - supply input often enough to prevent a spurious error indication. - For the typical 1-second cycle time of GPSes this implies a minimum - 2-second timeout. - -* Blocking read for data from the daemon. Named something like "read()" - (this was "poll()" in older versions). - -* Close the session socket. Named something like "close()". - -* Enable debugging trace messages - -The fact that the data-waiting check and the read both block means -that, if your application has to deal with other input sources than -the GPS, you will probably have to isolate the read loop in a thread with -a mutex lock on the gps_data structure. - -Here is a complete table of the binding entry points: - -.Entry points in client bindings -[frame="topbot",options="header"] -|======================================================================== -|C |C++ |Python | -Function -|gps_open() |gpsmm.gpsmm() |gps.\_\_init__() | -In OO languages the client class initializer opens the daemon socket. -|gps_send() |gpsmm.send() |gps.send() | -Send wire-protocol commands to the daemon. Deprecated and unstable. -|gps_stream() |gpsmm.stream() |gps.stream() | -Set watch policy. What you should use instead of send(). -|gps_waiting() |gpsmm.waiting() |gps.waiting() | -Blocking check with timeout to see if input is waiting. -|gps_read() |gpsmm.read() |gps.read() | -Blocking read for data from the daemon. -|gps_unpack() | |gps.unpack() | -Parse JSON from a specified buffer into a session structure -|gps_close() |gpsmm.~gpsmm() |gps.close() | -Close the daemon socket and end the session. -|gps_data() |gpsmm.data() |gps.data() | -Get the contents of the client buffer. -|gps_enable_debug() |gpsmm_enable_debug() | | -Enable debug tracing. Only useful for GPSD developers. -|gps_clear_fix() |gpsmm.clear_fix() | | -Clear the contents of the fix structure. -|======================================================================== - -The tricky part is interpreting what you get from the blocking -read. The reason it's tricky is that you're not guaranteed that -every read will pick up exactly one complete JSON object from the -daemon. It may grab one response object, or more than one, or -part of one, or one or more followed by a fragment. - -What the library does on each read is this: get what it can from the -socket, append that to a private buffer, and then consume as many JSON -objects from the front of the buffer as it can. Any incomplete JSON -is left in the private buffer to be completed and unpacked on a later -go-round. - -In C, the library "consumes" a JSON object by unpacking its content -into a blackboard structure passed to the read entry point by -address. The structure contains a state-flag mask that you can (and -should!) check so you'll know which parts of the structure contain -valid data. It is safe to do nothing unless the PACKET_SET mask bit -is on, which is the library's way of telling you that at least one -complete JSON response has arrived since the last read. - -Data may accumulate on the blackboard over multiple reads, -with new TPV reports overwriting old ones; it is guaranteed that -overwrites are not partial. Expect this pattern to be replicated -in any compiled language with only fixed-extent structures. - -In Python and Perl the read entry point returns an object containing -accumulated data. The state-flag mask is still useful for telling you -which parts contain data, and there is still a PACKET_SET bit. Expect -this pattern to be replicated in other dynamic OO languages when we -support them. - -The C++ binding is a very thin wrapper around the C. You get back an -object, but it's just a reference to the C blackboard structure. There's -no unpack() method because it doesn't fit the gpsmm object's RAII model. - -All bindings will throw a recognizable error from the read entry -point when the socket is closed from the daemon side. - -[WARNING] -The timing of your read loop is important. When it has satellite lock, -the daemon will be writing into its end of the socket once per -whatever the normal reporting-cycle time of your device is - for a GPS -normally one peer second. *You must poll the socket more often that -that.* - -If necessary, spawn a worker thread to do this, mutex-locking the -structure where it outs the reports. If you don't do this, data -will back up in your socket buffers and position reports will be -more and more delayed until the socket FIFO fills, at which point the -daemon will conclude the client has died and drop the connection. - -AIVDM clients have a longer maximum allowable poll interval, but a -problem of a different kind. you have the problem that later sentences -of (say) Type 1 don't obsolete the data in earlier ones. This is a -problem, because the library is designed so that read calls pull any -JSON reports waiting from the daemon and interpret them all. - -To avoid losing data, you want to poll the daemon more often than once -per two seconds (that being the minimum transmission period for the -most frequently shipped sentences, Type 1/2/3). That way the read -buffer will never contain both a message and a later message of the -same type that steps on it. - -=== Shared-memory interface === - -Whenever gpsd recognizes a packet from any attached device, it writes -the accumulated state from that device to a shared memory segment. The -C and C++ client libraries shipped with GPSD can read this segment. - -The API for reading the segment uses the same gps_open(), gps_read() -and gps_close() entry points as the sockets interface. To enable using -shared memory instead, it is only necessary to use the macro constant -GPSD_SHARED_MEMORY as the host argument of gps_open(). - -The gps_stream(), gps_send(), gps_waiting(), and gps_data() entry -points are not available with this interface. You cannot set a device -filter on it. You will not get device activation or deactivation -notices through it. And, of course, it is only good for local and not -networked access. Its main advantage is that it is very fast and -lightweight, especially suitable for use in low-power embedded -deployments with a single device on a fixed port and the sockets -interface configured out. - -Under the shared-memory interface, gps_read() after a successful -gps_open() will always return with data; its return is the size of a -struct gps_data_t in bytes. The 'gps_fd' member of the struct gpsdata -instance handed to you will always be -1. The PACKET_SET flag will -always be asserted. The other flag bits in the 'set' member will tell -you what data is updated in the instance, just as in the sockets -interface. - -The shared-memory interface is not yet available from Python. - -=== D-Bus broadcasts === - -If your system supports D-Bus, gpsd broadcasts a signal with path /org/gpsd, -interface "org.gpsd", and name "fix" whenever it received a position -report from any device attached to it. See the gpsd(8) manual page for -details of the binary payload layout. - -== C Examples == - -The source distribution includes two example clients in C; -gpxlogger.c and cgps.c. - -gpxlogger.c illustrates the simplest possible program flow; open, -followed by stream, followed by the library main loop. - -cgps.c shows what an interactive application using the library and -also hw processing user commands works. Note the use of the curses -nodelay function to ensure that wgetch() does not block the GPS -polling loop. - -== C++ examples == - -The following code skeleton implements a C++ client: - ----------------------------------------------------------------------- - -int main(void) -{ - gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT); - - if (gps_rec.stream(WATCH_ENABLE|WATCH_JSON) == NULL) { - cerr << "No GPSD running.\n"; - return 1; - } - - for (;;) { - struct gps_data_t* newdata; - - if (!gps_rec.waiting(50000000)) - continue; - - if ((newdata = gps_rec.read()) == NULL) { - cerr << "Read error.\n"; - return 1; - } else { - PROCESS(newdata); - } - } - return 0; -} - ----------------------------------------------------------------------- - -Note the absence of explicit open and close methods. The object -interface is designed on the RAII (Resource Acquisition Is -Initialization) model; you close it by deallocating it. - -Look at test_gpsmm.cpp in the distribution for a full example. - -== Python examples == - -There's a very simple Python example analogous to gpxlogger attached -to the source code for the gps.py library. - -The heart of it is this code: - ------------------------------------------------------------------------------ - session = gps(**opts) - session.stream(WATCH_ENABLE|WATCH_NEWSTYLE) - for report in session: - print report ------------------------------------------------------------------------------ - -If you need to intersperse other processing in a main event loop, -like this: - ----------------------------------------------------------------------- - -session = gps(mode=WATCH_ENABLE) -try: - while True: - # Do stuff - report = session.next() - # Check report class for 'DEVICE' messages from gpsd. If - # we're expecting messages from multiple devices we should - # inspect the message to determine which device - # has just become available. But if we're just listening - # to a single device, this may do. - if report['class'] == 'DEVICE': - # Clean up our current connection. - session.close() - # Tell gpsd we're ready to receive messages. - session = gps(mode=WATCH_ENABLE) - # Do more stuff -except StopIteration: - print "GPSD has terminated" - ----------------------------------------------------------------------- - -Each call to the iterator yields a report structure until the daemon -terminates, at which point the iterator next() method will raise -StopIteration and the loop will terminate. - -The report object returned by next() can be accessed either as a dictionary -or as an object. As a dictionary, it is the raw contents of the last -JSON response re-encoded in plain ASCII. For convenience, you may -also access it as an object with members for each attribute in the -dictionary. It is especially useful to know that the object will -always have a "class" member giving the response type (TPV, SKY, -DEVICE, etc.) as a string. - -For more interesting examples integrated with X and GTK, see xgps and -xgpsspeed. - -== Other Client Bindings == - -There are a couple of client bindings for GPSD that are maintained -separately from the GPSD distribution. We don't try to document their -APIs here, but just provide pointers to them. - -== Java == - -There is a Java binding, described at http://gpsd4java.forge.hoegergroup.de/ -This binding is available at maven central. See that web page for how -to use it in a maven build. - -== Perl == - -There's a Perl client library at http://search.cpan.org/dist/Net-GPSD3/ - -== Backward Incompatibility and Future Changes == - -The C/C++ binding makes available two preprocessor symbols, -GPSD_API_MAJOR_VERSION and GPSD_API_MINOR_VERSION, in gps.h. -The Python module has corresponding symbols. - -In major versions before 5: - -* gps_open() didn't take a third argument; instead, it returned malloc storage. - -* The 'read()' method in various bindings was named 'poll()', blocked - waiting for input, and had a different return convention. The name - 'poll()' will at some point be reintroduced as an interface to the - wire-protocol POLL command. - -* Clients needed to define a hook for client-side logging if they - didn't want code in netlib.c and libgps_core.c to occasionally send - messages to stderr. This requirement is now gone. - -* There was a set_raw_hook() method in the C and Python bindings, now gone. - C clients should call gps_data(); the buffer is available directly in Python, - both as str (response) and bytes (bresponse). The distinction matters - in Python 3. - -//end diff --git a/www/gpsd-time-service-howto.adoc b/www/gpsd-time-service-howto.adoc new file mode 100644 index 00000000..a3204d65 --- /dev/null +++ b/www/gpsd-time-service-howto.adoc @@ -0,0 +1,1867 @@ += GPSD Time Service HOWTO = +:description: How to set up an NTP Stratum 1 server using GPSD. +:keywords: time, GPSD, NTP, time, precision, 1PPS, PPS, stratum, jitter +Gary E. Miller , Eric S. Raymond +v2.10, Sep 2016 + +This document is mastered in asciidoc format. If you are reading it in HTML, +you can find the original at the GPSD project website. + +== Introduction == + +GPSD, NTP and a GPS receiver supplying 1PPS (one pulse-per-second) +output can be used to set up a high-quality NTP time server. This +HOWTO explains the method and various options you have in setting it +up. + +Here is the quick-start sequence. The rest of this document goes +into more detail about the steps. + +1. Ensure that gpsd and either ntpd or chronyd are installed on your + system. (Both gpsd and ntpd are preinstalled in many stock Linux + distributions; chronyd is normally not.) You don't have to choose + which to use yet if you have easy access to both, but knowing which + alternatives are readily available to you is a good place to start. + +2. Verify that your gpsd version is at least 3.17. Many problems are + caused by the use of old versions. When in doubt, reinstall + gpsd from the upstream source. Many distributions ship old + and/or broken versions of gpsd. + +3. Connect a PPS-capable GPS receiver to one of your serial or USB + ports. A random cheap consumer-grade GPS receiver won't do; you + may have to do some hunting to find a usable one. + +4. Check that it actually emits PPS by pointing GPSD's gpsmon utility + at the port. If it has a good (3D-mode) fix, lines marked "PPS" + should scroll by in the packet-logging window. A new device out of + the box may take up to 30 minutes for the first 3D fix. If gpsmon + shows a 3D fix, but does not show PPS lines, try running ppscheck. + +5. If you persistently fail to get live PPS, (a) you may have a + skyview problem, (b) you may have a cabling problem, (c) your GPS + may not support PPS, (d) you may have a gpsd or kernel configuration + problem, (e) you may have a device problem, (e) there may be a bug + in the core GPSD code used by gpsmon. These are listed in roughly + decreasing probability. Troubleshoot appropriately. + +6. Edit your ntpd or chronyd configuration to tell your NTP daemon to + listen for time hints. (This step is somewhat tricky.) + +7. Start up gpsd. If you are using ntpd, you can use ipcrm(1) to check that + verify that the shared-memory segment that gpsd and ntpd want to + use to communicate has been attached; or you can impatiently skip + to the next step and look for the segment only if that fails. + +8. Use ntpq or the chronyc sources command to verify that your device + is feeding time corrections to your NTP daemon. + +9. (Optional and challenging.) Hand-tune your installation for the + best possible performance. + +This document does not attempt to explain all the intricacies of time +service; it is focused on practical advice for one specific deployment +case. There is an introduction <> to basic concepts and +terminology for those new to time service. An overview of the NTP +protocols can be found at <>, and the official NTP FAQ +<> is probably as gentle an introduction to the NTP reference +implementation as presently exists. + +We encourage others to contribute additions and corrections. + +.Units table +|==================================================== +| nSec | nanoSecond | 1/1,000,000,000 of a second +| uSec | microSecond | 1/1,000,000 of a second +| mSec | milliSecond | 1/1,000 of a second +|==================================================== + +There are a few important terms we need to define up front. *Latency* +is delay from a time measurement until a report on it arrives where it +is needed. *Jitter* is short-term variation in latency. *Wobble* is a +jitter-like variation that is long compared to typical measurement +periods. *Accuracy* is the traceable offset from 'true' time as +defined by a national standard institute. + +A good analogy to jitter vs wobble is changes in sea level on a beach. +Jitter is caused by wave action, wobble is the daily effect of tides. +For a time server, the most common causes of wobble are varying GPS +satellite geometries and the effect of daily temperature variations on +the oscillators in your equipment. + +== NTP with GPSD == + +See <> for a technical description of how NTP corrects +your computer's clock against wobble. For purposes of this how-to, the +important concepts to take way are those of time strata, servers, and +reference clocks. + +Ordinary NTP client computers are normally configured to get time from +one or more Stratum 2 (or less commonly Stratum 3) NTP +servers. However, with GPSD and a suitable GPS receiver, you can easily +condition your clock to higher accuracy than what you get from typical +Stratum 2; with a little effort, you can do better than you can get +from most public Stratum 1 servers. + +You can then make your high-quality time available to other systems on +your network, or even run a public NTP server. Anyone can do this; +there is no official authority, and any NTP client may choose to use +your host as a server by requesting time from it. The time-service +network is self-regulating, with NTP daemons constantly pruning +statistical outliers so the timebase cannot be accidentally or +deliberately compromised. + +In fact many public and widely-trusted Stratum 1 servers use GPS +receivers as their reference clocks, and a significant fraction of +those use GPSD in the way we will describe here. + +== GPS time == + +The way time is shipped from GPS satellites causes problems to +beware of in certain edge cases. + +Date and time in GPS is represented as number of weeks from the start +of zero second of 6 January 1980, plus number of seconds into the +week. GPS time is *not* leap-second corrected, though satellites also +broadcast a current leap-second correction which is updated on +six-month boundaries according to rotational bulletins issued by the +International Earth Rotation and Reference Systems Service (IERS). + +The leap-second correction is only included in the multiplexed satellite +subframe broadcast, once every 12.5 minutes. While the satellites do +notify GPSes of upcoming leap-seconds, this notification is not +necessarily processed correctly on consumer-grade devices, and may not +be available at all when a GPS receiver has just cold-booted. Thus, +reported UTC time may be slightly inaccurate between a cold boot or leap +second and the following subframe broadcast. + +GPS date and time are subject to a rollover problem in the 10-bit week +number counter, which will re-zero every 1024 weeks (roughly every 19.6 +years). The last rollover (and the first since GPS went live in 1980) +was in Aug-1999; the next will fall in Apr-2019. The new "CNAV" data +format extends the week number to 13 bits, with the first rollover +occurring in Jan-2137, but this is only used with some newly added GPS +signals, and is unlikely to be usable in most consumer-grade receivers +prior to the 2019 rollover. + +For accurate time reporting, therefore, a GPS requires a supplemental +time references sufficient to identify the current rollover period, +e.g. accurate to within 512 weeks. Many GPSes have a wired-in (and +undocumented) assumption about the UTC time of the last rollover and +will thus report incorrect times outside the rollover period they were +designed in. + +For accurate time service via GPSD, you require three things: + +* A GPS made since the last rollover, so its hidden assumption about + the epoch will be correct. + +* Enough time elapsed since a cold boot or IERS leap-second adjustment + for the current leap-second to get update. + +* A GPS that properly handles leap-second adjustments. Anything + based on a u-blox from v6 onward should be good; the status of + SiRFs is unknown and doubtful. + +== 1PPS quality issues == + +GPSD is useful for precision time service because it can use the 1PPS +pulse delivered by some GPS receivers to discipline (correct) a local +NTP instance. + +It's tempting to think one could use a GPS receiver for time service +just by timestamping the arrival of the first character in the report +on each fix and correcting for a relatively small fixed latency +composed of fix-processing and RS232 transmission time. + +At one character per ten bits (counting framing and stopbits) a +9600-bps serial link introduces about a mSec of latency *per +character*; furthermore, your kernel will normally delay delivery +of characters to your application until the next timer tick, about +every 4 mSec in modern kernels. Both USB and RS232 will incur that +approximately 5mSec-per-char latency overhead. You'll have to deal +with this latency even on chips like the Venus 6 that claim the +beginning of their reporting burst is synced to PPS. (Such claims are +not always reliable, in any case.) + +Unfortunately, fix reports are also delayed in the receiver and on +the link by as much as several hundred mSec, and this delay is not +constant. This latency varies (wobbles) throughout the day. It may be +stable to 10 mSec for hours and then jump by 200mSec. Under these +circumstances you can't expect accuracy to UTC much better than 1 +second from this method. + +For example: SiRF receivers, the make currently most popular in +consumer-grade GPS receivers, exhibit a wobble of about 170mSec in the +offset between actual top-of-second and the transmission of the first +sentence in each reporting cycle. You can see this graphed at +<>. + +To get accurate time, then, the in-band fix report from the GPS +receiver needs to be supplemented with an out-of-band signal that has +a low and constant or near-constant latency with respect to the time +of of the fix. GPS satellites deliver a top-of-GPS-second +notification that is nominally accurate to 50nSec; in capable GPS +receivers that becomes the 1PPS signal. + +1PPS-capable GPS receivers use an RS-232 control line to ship the 1PPS +edge of second to the host system (usually Carrier Detect or Ring +Indicator; GPSD will quietly accept either). Satellite top-of-second +loses some accuracy on the way down due mainly to variable delays in +the ionosphere; processing overhead in the GPS receiver itself adds a +bit more latency, and your local host detecting that pulse adds still +more latency and jitter. But it's still often accurate to on the +order of 1 uSec. + +Under most Unixes there are two ways to watch 1PPS; Kernel PPS (KPPS) +and plain PPS latching. KPPS is an implementation of RFC 2783 <>. +Plain PPS just references the pulse to the system clock as +measured in user space. These have different error budgets. + +Kernel PPS uses a kernel function to accurately timestamp the status +change on the PPS line. Plain PPS has the kernel wake up the GPSD PPS +thread and then the PPS thread reads the current system clock. As +noted in the GPSD code, having the kernel do the time stamp yields +lower latency and less jitter. Both methods have accuracy degraded by +interrupt-processing latency in the kernel serial layer, but plain +PPS incurs additional context-switching overhead that KPPS does not. + +With KPPS it is very doable to get the system clock stable to ±1 +uSec. Otherwise you are lucky to get ±5 uSec, and there will be +about 20uSec of jitter. All these figures were observed on +plain-vanilla x86 PCs with clock speeds in the 2GHz range. + +All the previous figures assume you're using PPS delivered over RS232. +USB GPS receivers that deliver 1PPS are rare, but do exist. Notably, +there's the Navisys GR-601W/GR-701W/GR-801W <>. In case these devices go +out of production it's worth noting that they are a trivial +modification of the stock two-chip-on-a-miniboard +commodity-GPS-receiver design of engine plus USB-to-serial adapter; +the GR-[678]01W wires a u-blox 6/7/8 to a Prolific Logic PL23203. To +get 1PPS out, this design just wires the 1PPS pin from the GPS engine +to the Carrier Detect pin on the USB adapter. (This is known as the +"Macx-1 mod".) + +With this design, 1PPS from the engine will turn into a USB event that +becomes visible to the host system (and GPSD) the next time the USB +device is polled. USB 1.1 polls 1024 slots every second. Each slot is +polled in the same order every second. When a device is added it is +assigned to one of those 1024 polling slots. It should then be clear +that the accuracy of a USB 1.1 connected GPS receiver would be about 1 +mSec. + +As of mid-2016 no USB GPS receiver we know of implements the higher +polling-rate options in USB 2 and 3 or the interrupt capability in USB +3. When one does, and if it has the Macx-1 mod, higher USB accuracy +will ensue. + +.Summary of typical accuracy +|===================================================== +| GPS atomic clock | ±50nSec +| KPPS | ±1uSec +| PPS | ±5uSec +| USB 1.1 poll interval | ±1mSec +| USB 2.0 poll interval | ±100μSec (100000 nSec) +| Network NTP time | ~±30mSec footnote:[RFC5905 says "a few tens of milliseconds", but asymmetric routing can produce 100mSec offset] +|===================================================== + +Observed variations from the typical figure increase towards the bottom +of the table. Notably, a heavily loaded host system can reduce PPS +accuracy further, though not KPPS accuracy except in the most extreme +cases. The USB poll interval tends to be very stable (relative to its +1mSec or 100μSec base). + +Network NTP time accuracy can be degraded below RFC5905's "a few tens +of milliseconds" by a number of factors. Almost all have more to do +with the quality of your Internet connection to your servers than with +the time accuracy of the servers themselves. Some negatives: + +* Having a cable modem. That is, as opposed to DSL or optical fiber, which + tend to have less variable latencies. + +* Path delay asymmetries due to peering policy. These can confuse + NTP's reconciliation algorithms. + +With these factors in play, worst-case error can reach up to +±100mSec. Fortunately, errors of over ±100mSec are +unusual and should occur only if all your network routes to servers +have serious problems. + +== Software Prerequisites == + +If your kernel provides the RFC 2783 KPPS (kernel PPS) API, gpsd will +use that for extra accuracy. Many Linux distributions have a package +called "pps-tools" that will install KPPS support and the timepps.h +header file. We recommend you do that. If your kernel is built in +the normal modular way, this package installation will suffice. + +=== Building gpsd == + +A normal gpsd build includes support for interpreting 1PPS pulses that +is mostly autoconfiguring and requires no special setup. + +You can build a version stripped to the mimimum configuration required +for time service. This reduces the size of the binary and may be +helpful on embedded systems or for SBCs like the Raspberry Pi, Odroid, +or BeagleBone. Also, when gpsd is built in this way, the -n (nowait) +option is forced; gpsd opens its command-line devices immediately on +startup. + +Do it like this: + +----------------------------------------------------------------------------- +scons timeservice=yes nmea0183=yes fixed_port_speed=9600 fixed_stop_bits=1 +----------------------------------------------------------------------------- + +You may substitute a different GPS (e.g. "ublox" or "sirf"), You can +also fix the serial parameters to avoid autobauding lag; the code +assumes 8 bit bytes, so the above locks the daemon to 9600 8N1. Besides +the daemon, this also builds gpsmon and ntpshmmon. + +Otherwise, make sure the build is with pps=yes and ntpshm=yes (the +default). The command "gpsd -L" should indicate that time-service +features and PPS are enabled. + +=== Kernel support === + +If you are scratch-building a Linux kernel, the configuration +must include either these two lines, or the same with "y" replaced +by "m" to enable the drivers as modules: + +----------------------------------------------------------------------------- +CONFIG_PPS=y +CONFIG_PPS_CLIENT_LDISC=y +----------------------------------------------------------------------------- + +Some embedded systems, like the Raspberry Pi, detect PPS on a GPIO +line instead of an a serial port line. For those systems you will +also need these two lines: + +----------------------------------------------------------------------------- +CONFIG_PPS_CLIENT_GPIO=y +CONFIG_GPIO_SYSFS=y +----------------------------------------------------------------------------- + +Your Linux distribution may ship a file /boot/config-XXX (where XXX is +the name of a kernel) or one called /proc/config.gz (for the running +kernel). This will have a list of the configuration options that were +used to build the kernel. You can check if the above options are +set. Usually they will be set to "m", which is sufficient. + +NetBSD has included the RFC2783 Pulse Per Second API for real serial +ports by default since 1998, and it works with ntpd. NetBSD 7 +(forthcoming) includes RFC2783 support for USB-serial devices, and +this works (with ntpd) with the GR-601W/GR-701W/GR-801W. However, +gpsd's code interacts badly with the NetBSD implementation, and gpsd's +support for RFC2783 PPS does not yet work on NetBSD (for serial or +USB). + +Other OSes have different ways to enable KPPS in their kernels. +When we learn what those are, we'll document them or point +at references. + +=== Time service daemon === + +You will need to have either ntpd or chrony installed. If you are +running a Unix variant with a package system, the packages will +probably be named 'ntp' (or 'ntpsec') and either 'chrony' or 'chronyd'. + +Between ntp and chrony, ntp is the older and more popular choice - +thus, the one with the best-established peer community if you need +help in unusual situations. On the other hand, chrony has a +reputation for being easier to set up and configure, and is better in +situations where your machine has to be disconnected from the Internet +for long enough periods of time for the clock to drift significantly. + +ntpd and chrony have differing philosophies, with ntpd more interested +in deriving consensus time from multiple sources while chrony tries to +identify a single best source and track it closely. + +A feature comparison, part of the chrony documentation, is at +<>. An informative email thread about the differences +is <>. If you don't already know enough about time +service to have a preference, the functional differences between them +are unlikely to be significant to you; flip a coin. + +If you choose ntpd, it's best to go with the NTPsec version rather +than legacy ntpd. (As of September 2016 NTPsec is not yet generally +available in binary package form. You will have to build it from +source.) NTPsec shares some maintainers with GPSD, and has some +significant improvements in security and performance. + +== Choice of Hardware == + +To get 1PPS to your NTP daemon, you first need to get it from a +PPS-capable GPS receiver. As of early 2015 this means either the +previously mentioned GR devices or a serial GPS receiver with 1PPS. + +You can find 1PPS-capable devices supported by GPSD at <>. +Note that the most popular consumer-grade GPS receivers do not usually +deliver 1PPS through USB or even RS232. The usual run of cheap GPS +mice won't do. In general, you can't use a USB device for time +service unless you know it has the Macx-1 mod. + +In the past, the RS232 variant of the Garmin GPS-18 has been very +commonly used for time service (see <> for a typical setup very +well described). While it is still a respectable choice, newer +devices have better sensitivity and signal discrimination. This makes +them superior for indoor use as time sources. + +In general, use a GPS receiver with an RS232 interface for time +service if you can. The GR-601W was designed (by one of the authors, +as it happens) for deployment with commodity TCP/IP routers that only +have USB ports. RS232 is more fiddly to set up (with older devices +like the GPS-18 you may even have to make your own cables) but it can +deliver three orders of magnitude better accuracy and repeatability - +enough to meet prevailing standards for a public Stratum 1 server. + +Among newer receiver designs the authors found the the u-blox line of +receivers used in the GR-[678]01W to be particularly good. Very +detailed information on its timing performance can be found at +<>. One of us (Raymond) has recent experience with an +eval kit, the EVK 6H-0-001, that would make an excellent Stratum 0 +device. + +Both the EVK 6H and GR-601W are built around the LEA-6H module, which +is a relatively inexpensive but high-quality navigation GPS +receiver. We make a note of this because u-blox also has a specialized +timing variant, the LEA 6T, which would probably be overkill for an +NTP server. (The 6T does have the virtue that you could probably get a +good fix from one satellite in view once it knows its location, but +the part is expensive and difficult to find.) + +Unfortunately as of early 2015 the LEA-6H is still hard to find in a +packaged RS232 version, as opposed to a bare OEM module exporting TTL +levels or an eval kit like the EVK 6H-0-001 costing upwards of +US$300. Search the web; you may find a here-today-gone-tomorrow offer +on alibaba.com or somewhere similar. + +The LEA-6T, and some other higher-end GPS receivers (but not the +LEA-6H) have a stationary mode which, after you initialize it with the +device's location, can deliver time service with only one good +satellite lock (as opposed to the three required for a fix in its +normal mode). For most reliable service we recommend using stationary +mode if your device has it. GPSD tools don't yet directly support +this, but that capability may be added in a future release. + +The design of your host system can also affect time quality. The +±5uSec error bound quoted above is for a dual-core or better +system with clock in the 2GHz range on which the OS can schedule the +long-running PPS thread in GPSD on an otherwise mostly unused +processor (the Linux scheduler, in particular, will do this). On a +single-core system, contention with other processes can pile +on several additional microseconds of error. + +If you are super-serious about your time-nuttery, you may want to look +into the newest generation of dedicated Stratum 1 microservers being +built out of open-source SBCs like the Raspberry Pi and Beaglebone, or +sometimes with fully custom designs. A representative build is well +described at <>. + +These microserver designs avoid load-induced jitter by being fully +dedicated to NTP service. They are small, low-powered devices and +often surprisingly inexpensive, as in costing less than US$100. They +tend to favor the LEA-6H, and many of them use preinstalled GPSD on +board. + +== Enabling PPS == + +You can determine whether your GPS receiver emits 1PPS, and gpsd is +detecting it, by running the gpsmon utility (giving it the GPS +receiver's serial-device path as argument). Watch for lines of dashes +marked 'PPS' in the packet-logging window; for most GPS receiver types +there will also be a "PPS offset:" field in the data panels above +showing the delta between PPS and your local clock. + +If you don't have gpsmon available, or you don't see PPS lines in it, +you can run ppscheck. As a last resort you can gpsd at -D 5 and watch +for PPS state change messages in the logfile. + +If you don't see evidence of incoming PPS, here are some trouble +sources to check: + +1. The skyview of your GPS receiver may be poor. Suspect this if, + when you watch it with gpsmon, it wanders in and out of having a + good 3D fix. Unfortunately, the only fix for this is to re-site + your GPS where it can see more sky; fortunately, this is not as + common a problem as it used to be, because modern receivers are + often capable of getting a solid fix indoors. + +2. If you are using an RS232 cable, examine it suspiciously, ideally + with an RS232 breakout box. Cheap DB9 to DB9 cables such as those + issued with UPSes often carry TXD/RXD/SG only, omitting handshake + lines such as DCD, RI, and DSR that are used to carry 1PPS. + Suspect this especially if the cable jacket looks too skinny to + hold more than three leads! + +3. Verify that your gpsd and kernel were both built with PPS support, + as previously described in the section on software prerequisites. + +4. Verify that the USB or RS232 device driver is accepting the ioctl + that tells it to wait on a PPS state change from the device. The + messages you hope *not* to see look like "KPPS cannot set PPS line + discipline" and "PPS ioctl(TIOCMIWAIT) failed". The former + can probably be corrected by running as root; the latter (which + should never happen with an RS232 device) probably means your USB + device driver lacks this wait capability entirely and cannot be + used for time service. + +5. If you have a solid 3D fix, a known-good cable, your software is + properly configured, the wait ioctl succeeded, but you still get no + PPS, then you might have a GPS receiver that fails to deliver PPS + off the chip to the RS232 or USB interface. You get to become + intimate with datasheets and pinouts, and might need to acquire a + different GPS receiver. + +== Running GPSD == + +If you're going to use gpsd for time service, you must run in -n mode +so the clock will be updated even when no clients are active. This option +is forced if you built GPSD with timeservice=yes as an option. + +Note that gpsd assumes that after each fix the GPS receiver will +assert 1PPS first and ship sentences reporting time of fix +second (and the sentence burst will end before the next 1PPS). Every +GPS we know of does things in this order. (However, on some very old +GPSes that defaulted to 4800 baud, long sentence bursts - notably +those containing a skyview - could slop over into the next second.) + +If you ever encounter an exception, it should manifest as reported +times that look like they're from the future and require a negative +fudge. If this ever happens, please report the device make and model +to the GPSD maintainers so we can flag it in our GPS hardware +database. + +There is another possible cause of small negative offsets which +shows up on the GR-601W: implementation bugs in your USB driver, +combining with quantization by the USB poll interval. This +doesn't mean the u-blox 6 inside it is actually emitting PPS +after the GPS timestamp is shipped. + +In order to present the smallest possible attack surface to +privilege-escalation attempts, gpsd, if run as root, drops its root +privileges very soon after startup - just after it has opened any +serial device paths passed on the command line. + +Thus, KPPS can only be used with devices passed that way, not with +GPSes that are later presented to gpsd by the hotplug system. Those +hotplug devices may, however, be able to use plain, non-kernel +PPS. gpsd tries to automatically fall back to this when absence of +root permissions makes KPPS unavailable. + +In general, if you start gpsd as other than root, the following things +will happen that degrade the accuracy of reported time: + +1. Devices passed on the command line will be unable to use KPPS and +will fall back to the same plain PPS that all hotplug devices must +use, increasing the associated error from ~1 uSec to about ~5 uSec. + +2. gpsd will be unable to renice itself to a higher priority. This +action helps protect it against jitter induced by variable system +load. It's particularly important if your NTP server is a general-use +computer that's also handling mail or web service or development. + +3. The way you have to configure ntpd and chrony will change away +from what we show you here; ntpd will need to be told different +shared-memory segment numbers, and chronyd will need a different +socket location. + +You may also find gpsd can't open serial devices at all if your +OS distribution has done "secure" things with the permissions. + +== Feeding NTPD from GPSD == + +Most Unix systems get their time service through ntpd, a very old and +stable open-source software suite which is the reference +implementation of NTP. The project home page is <>. We +recommend using NTPsec, a recent fork that is improved and +security-hardened <>. + +When gpsd receives a sentence with a timestamp, it packages the +received timestamp with current local time and sends it to a +shared-memory segment with an ID known to ntpd, the network time +synchronization daemon. If ntpd has been properly configured to +receive this message, it will be used to correct the system clock. + +When in doubt, the preferred method to start your timekeeping is: + +----------------------------------------------------------------------------- +$ su - (or sudo -s ) +# killall -9 gpsd ntpd +# gpsd -n /dev/ttyXX +# sleep 2 +# ntpd -gN +# sleep 2 +# cgps +----------------------------------------------------------------------------- + +where /dev/ttyXX is whatever 1PPS-capable device you have. In a +binary-package-based Linux distribution it is probable that ntpd +will already have been launched at boot time. + +It's best to have gpsd start first. That way when ntpd restarts it has +a good local time handy. If ntpd starts first, it will set the local +clock using a remote, probably pool, server. Then ntpd has to spend a +whole day slowly resynching the clock. + +If you're using dhcp3-client to configure your system, make sure +you disable /etc/dhcp3/dhclient-exit-hooks.d/ntp, as dhclient would +restart ntpd with an automatically created ntp.conf otherwise - and +gpsd would not be able to talk with ntpd any more. + +While gpsd may be runnable as non-root, you will get significantly +better accuracy of time reporting in root mode; the difference, while +almost certainly insignificant for feeding Stratum 1 time to clients +over the Internet, may matter for PTP service over a LAN. Typically +only root can access kernel PPS, whereas in non-root mode you're limited to +plain PPS (if that feature is available). As noted in the previous +section on 1PPS quality issues, this difference has performance +implications. + +The rest of these setup instructions will assume that you are starting +gpsd as root, with occasional glances at the non-root case. + +Now check to see if gpsd has correctly attached the shared-memory +segments in needs to communicate with ntpd. ntpd's rules for the +creation of these segments are: + +Segments 0 and 1:: + Permissions are 0600 - other programs can only read and + write this segment when running as root. + +Segments 2, 3 and above:: + Permissions are 0666 - other programs can read + and write as any user. If ntpd has been + configured to use these segments, any + unprivileged user is allowed to provide data + for synchronization. + +Because gpsd can be started either as root or non-root, it checks and +attaches the more privileged segment pair it can - either 0 and 1 or 2 +and 3. + +For each GPS receiver that gpsd controls, it will use the attached ntpshm +segments in pairs (for coarse clock and pps source, respectively) +starting from the first found segments. + +To debug, try looking at the live segments this way + +----------------------------------------------------------------------------- +# ipcs -m +----------------------------------------------------------------------------- + +If gpsd was started as root, the results should look like this: + +----------------------------------------------------------------------------- + ------ Shared Memory Segments -------- + key shmid owner perms bytes nattch status + 0x4e545030 0 root 700 96 2 + 0x4e545031 32769 root 700 96 2 + 0x4e545032 163842 root 666 96 1 + 0x4e545033 196611 root 666 96 1 +----------------------------------------------------------------------------- + +For a bit more data try this: + +----------------------------------------------------------------------------- +cat /proc/sysvipc/shm +----------------------------------------------------------------------------- + +If gpsd cannot open the segments, check that you are not running SELinux +or apparmor. Either may require you to configure a security exception. + +If you see the shared segments (keys 1314148400 -- 1314148403), and +no gpsd or ntpd is running then try removing them like this: + +----------------------------------------------------------------------------- +# ipcrm -M 0x4e545030 +# ipcrm -M 0x4e545031 +# ipcrm -M 0x4e545032 +# ipcrm -M 0x4e545033 +----------------------------------------------------------------------------- + +Here is a minimal sample ntp.conf configuration to work with GPSD run +as root, telling ntpd how to read the GPS notifications + +----------------------------------------------------------------------------- +pool us.pool.ntp.org iburst + +driftfile /var/lib/ntp/ntp.drift +logfile /var/log/ntp.log + +restrict default kod nomodify notrap nopeer noquery +restrict -6 default kod nomodify notrap nopeer noquery +restrict 127.0.0.1 mask 255.255.255.0 +restrict -6 ::1 + +# GPS Serial data reference (NTP0) +server 127.127.28.0 +fudge 127.127.28.0 time1 0.9999 refid GPS + +# GPS PPS reference (NTP1) +server 127.127.28.1 prefer +fudge 127.127.28.1 refid PPS +----------------------------------------------------------------------------- + +The number "0.9999" is a placeholder, to be explained shortly. It +is *not a number to be used in production* - it's too large. If you +can't replace it with a real value, it would be best to leave out the +clause entirely so the entry looks like + +----------------------------------------------------------------------------- +fudge 127.127.28.0 refid GPS +----------------------------------------------------------------------------- + +This is equivalent to declaring a time1 of 0. + +The pool statement adds a variable number of servers (often 10) as +additional time references needed by ntpd for redundancy and to give you +a reference to see how well your local GPS receiver is performing. If +you are outside of the USA replace the pool servers with one in your +local area. See <> for further information. + +The pool statement, and the driftfile and logfile declarations after it, +will not be strictly necessary if the default ntp.conf that your +distribution supplies gives you a working setup. The two pairs of +server and fudge declarations are the key. + +ntpd can be used in Denial of Service (DoS) attacks. To prevent that, +but still allow clients to request the local time, be sure the restrict +statements are in your ntpd config file. For more information see +<>. + +Users of ntpd versions older than revision ntp-4.2.5p138 should instead use +this ntp.conf, when gpsd is started as root: + +----------------------------------------------------------------------------- +pool us.pool.ntp.org iburst + +driftfile /var/lib/ntp/ntp.drift +logfile /var/log/ntp.log + +restrict default kod nomodify notrap nopeer noquery +restrict -6 default kod nomodify notrap nopeer noquery +restrict 127.0.0.1 mask 255.255.255.0 +restrict -6 ::1 + +# GPS Serial data reference (NTP0) +server 127.127.28.0 minpoll 4 maxpoll 4 +fudge 127.127.28.0 time1 0.9999 refid GPS + +# GPS PPS reference (NTP1) +server 127.127.28.1 minpoll 4 maxpoll 4 prefer +fudge 127.127.28.1 refid PPS +----------------------------------------------------------------------------- + +Users of ntpd versions prior to ntp-4.2.5 do not have the "pool" option. +Alternative configurations exist, but it is recommended that you upgrade +ntpd, if feasible. + +The magic pseudo-IP address 127.127.28.0 identifies unit 0 of the ntpd +shared-memory driver (NTP0); 127.127.28.1 identifies unit 1 (NTP1). +Unit 0 is used for in-band message timestamps and unit 1 for the (more +accurate, when available) time derived from combining in-band message +timestamps with the out-of-band PPS synchronization pulse. Splitting +these notifications allows ntpd to use its normal heuristics to weight +them. + +Different units - 2 (NTP2) and 3 (NTP3), respectively - must be used +when gpsd is not started as root. Some GPS HATs put PPS time on a GPIO +pin and will also use unit 2 (NTP2) for the PPS time correction. + +With this configuration, ntpd will read the timestamp posted by gpsd +every 64 seconds (16 if non-root) and send it to unit 0. + +The number after the parameter time1 (0.9999 in the example above) is a +"fudge", offset in seconds. It's an estimate of the latency between +the time source and the 'real' time. You can use it to compensate out +some of the fixed delays in the system. An 0.9999 fudge would be +ridiculously large. + +You may be able to find a value for the fudge by looking at the entry +for your GPS receiver type on <>. Later in this document +we'll explain methods for estimating a fudge factor on unknown +hardware. + +There is nothing magic about the refid fields; they are just labels +used for generating reports. You can name them anything you like. + +When you start gpsd, it will wait for a few good fixes before +attempting to process PPS. You should run gpsmon or cgps to verify +your GPS receiver has a 3D lock before worrying about timekeeping. + +After starting (as root) ntpd, then gpsd, a listing similar to the one +below should appear as the output of the command "ntpq -p" (after +allowing the GPS receiver to acquire a 3D fix). This may take up to +30 minutes if your GPS receiver has to cold-start or has a poor +skyview. + +----------------------------------------------------------------------------- + remote refid st t when poll reach delay offset jitter +============================================================================== +xtime-a.timefreq .ACTS. 1 u 40 64 377 59.228 -8.503 0.516 +-bonehed.lcs.mit 18.26.4.106 2 u 44 64 377 84.259 4.194 0.503 ++clock.sjc.he.ne .CDMA. 1 u 41 64 377 23.634 -0.518 0.465 ++SHM(0) .GPS. 0 l 50 64 377 0.000 6.631 5.331 +----------------------------------------------------------------------------- + +The line with refid ".GPS." represents the in-band time reports from +your GPS receiver. When you are getting PPS then it may look like +this: + +----------------------------------------------------------------------------- + remote refid st t when poll reach delay offset jitter +============================================================================== +xtime-a.timefreq .ACTS. 1 u 40 64 377 59.228 -8.503 0.516 +-bonehed.lcs.mit 18.26.4.106 2 u 44 64 377 84.259 4.194 0.503 ++clock.sjc.he.ne .CDMA. 1 u 41 64 377 23.634 -0.518 0.465 ++SHM(0) .GPS. 0 l 50 64 377 0.000 6.631 5.331 +*SHM(1) .PPS. 0 l 49 64 377 0.000 0.222 0.310 +----------------------------------------------------------------------------- + +Note the additional ".PPS." line. + +If the value under "reach" for the SHM lines remains zero, check that +gpsd is running; cgps reports a 3D fix; and the '-n' option was used. +Some GPS recievers specialized for time service can report time with signal +lock on only one satellite, but with most devices a 3D fix is +required. + +When the SHM(0) line does not appear at all, check your ntp.conf and +the system logs for error messages from ntpd. + +Notice the 1st and 3rd servers, stratum 1 servers, disagree by more than +8 mSec. The 1st and 2nd servers disagree by over 12 mSec. Our local +PPS reference agrees to the clock.sjc.he.net server within the expected +jitter of the GR-601W in use. + +When no other servers or local reference clocks appear in the NTP +configuration, the system clock will lock onto the GPS clock, but this +is a fragile setup - you can lose your only time reference if the GPS +receiver is temporarily unable to get satellite lock. + +You should always have at least two (preferably four) fallback servers +in your ntpd.conf for proper ntpd operation, in case your GPS receiver +fails to report time. The 'pool' command makes this happen. And +you'll need to adjust the offsets (fudges) in your ntp.conf so the +SHM(0) time is consistent with your other servers (and other local +reference clocks, if you have any). We'll describe how to diagnose and +tune your server configuration in a later section. + +Also note that after cold-starting ntpd it will calibrate for up to 15 +minutes before it starts adjusting the clock. Because the frequency +error estimate ("drift") that NTP uses isn't right when you first +start NTP, there will be a phase error that persists while the +frequency is estimated. So if your clock is a litle slow, then it +will keep getting behind, and the positive offset will cause NTP to +adjust the phase forward and also increase the frequency offset error. +After a day or so or maybe less the frequency estimate will be very +close and there won't be a persistent offset. + +The GPSD developers would like to receive information about the +offsets (fudges) observed by users for each type of receiver. If your +GPS receiver is not present in <>, or doesn't have a +recommended fudge, or you see a fudge value very different from what's +there, send us the output of the "ntpq -p" command and the make and +type of receiver. + +== Feeding chrony from GPSD == + +chrony is an alternative open-source implementation of NTP service, +originally designed for systems with low-bandwidth or intermittent +TCP/IP service. It interoperates with ntpd using the same NTP +protocols. Unlike ntpd which is designed to always be connected to +multiple internet time sources, chrony is designed for long periods +of offline use. Like ntpd, it can either operate purely as a client +or provide time service. The chrony project has a home page at +<>. Its documentation includes an instructive feature comparison +with ntpd at <>. + +gpsd, when run as root, feeds reference clock information to chronyd +using a socket named /var/run/chrony.ttyXX.sock (where ttyXX is +replaced by the GPS receiver's device name. This allows multiple GPS +receivers to feed one chronyd. + +No gpsd configuration is required to talk to chronyd. chronyd is +configured using the file /etc/chrony.conf or /etc/chrony/chrony.conf. +Check your distributions documentation for the correct location. To get +chronyd to connect to gpsd using the basic ntpd compatible SHM method +add this to use this basic chrony.conf file: + +----------------------------------------------------------------------------- +server 0.us.pool.ntp.org +server 1.us.pool.ntp.org +server 2.us.pool.ntp.org +server 3.us.pool.ntp.org + +driftfile /var/lib/chrony/drift + +allow + +# set larger delay to allow the NMEA source to overlap with +# the other sources and avoid the falseticker status +refclock SHM 0 refid GPS precision 1e-1 offset 0.9999 delay 0.2 +refclock SHM 1 refid PPS precision 1e-9 +----------------------------------------------------------------------------- + +You need to add the "precision 1e-9" on the SHM 1 line as chronyd fails +to read the precision from the SHM structure. Without knowing the high +precision of the PPS on SHM 1 it may not place enough importance on its +data. + +If you are outside of the USA replace the pool servers with one in your +local area. See <> for further information. + +The offset option is functionally like ntpd's time1 option, used to +correct known and constant latency. + +The allow option allows anyone on the internet to query your server's +time. + +To get chronyd to connect to gpsd using the more precise socket +method add this to your chrony.conf file (replacing ttyXX +with your device name). + +If running as root: + +----------------------------------------------------------------------------- +server 0.us.pool.ntp.org +server 1.us.pool.ntp.org +server 2.us.pool.ntp.org +server 3.us.pool.ntp.org + +driftfile /var/lib/chrony/drift + +allow + +# set larger delay to allow the NMEA source to overlap with +# the other sources and avoid the falseticker status +refclock SHM 0 refid GPS precision 1e-1 offset 0.9999 delay 0.2 +refclock SOCK /var/run/chrony.ttyXX.sock refid PPS +----------------------------------------------------------------------------- + +If not running as root change the "refclock SOCK" line to: + +----------------------------------------------------------------------------- +refclock SOCK /tmp/chrony.ttyXX.sock refid PPS +----------------------------------------------------------------------------- + +See the chrony man page for more detail on the configuration options +<>. + +Finally note that chronyd needs to be started before gpsd so the +socket is ready when gpsd starts up. + +If running as root, the preferred starting procedure is: + +----------------------------------------------------------------------------- +$ su - (or sudo -s ) +# killall -9 gpsd chronyd +# chronyd -f /etc/chrony/chrony.conf +# sleep 2 +# gpsd -n /dev/ttyXX +# sleep 2 +# cgps +----------------------------------------------------------------------------- + +After you have verified with cgps that your GPS receiver has a good 3D +lock you can check that gpsd is outputing good time by running ntpshmmon. + +----------------------------------------------------------------------------- +# ntpshmmon +ntpshmmon version 1 +# Name Seen@ Clock Real L Prec +sample NTP0 1461537438.593729271 1461537438.593633306 1461537438.703999996 0 -1 +sample NTP1 1461537439.000421494 1461537439.000007374 1461537439.000000000 0 -20 +sample NTP0 1461537439.093844900 1461537438.593633306 1461537438.703999996 0 -1 +sample NTP0 1461537439.621309382 1461537439.620958240 1461537439.703999996 0 -1 +sample NTP1 1461537440.000615395 1461537439.999994105 1461537440.000000000 0 -20 +sample NTP0 1461537440.122079148 1461537439.620958240 1461537439.703999996 0 -1 +^C +----------------------------------------------------------------------------- + +If you see only "NTP2", instead, you forgot to go root before starting gpsd. + +Once ntpshmmon shows good time data you can see how chrony is doing by +running 'chronyc sources'. Your output will look like this: + +----------------------------------------------------------------------------- +# chronyc sources + +210 Number of sources = 7 +MS Name/IP address Stratum Poll Reach LastRx Last sample +=============================================================================== +#- GPS 0 4 377 12 +3580us[+3580us] +/- 101ms +#* PPS 0 4 377 10 -86ns[ -157ns] +/- 181ns +^? vimo.dorui.net 3 6 377 23 -123ms[ -125ms] +/- 71ms +^? time.gac.edu 2 6 377 24 -127ms[ -128ms] +/- 55ms +^? 2001:470:1:24f::2:3 2 6 377 24 -122ms[ -124ms] +/- 44ms +^? 142.54.181.202 2 6 377 22 -126ms[ -128ms] +/- 73ms +----------------------------------------------------------------------------- + +The stratum is as in ntpq. The Poll is how many seconds elapse between samples. +The Reach is as in ntpq. LastRx is the time since the last successful +sample. Last sample is the offset and jitter of the source. + +To keep chronyd from preferring NMEA time over PPS time, you can add an +overlarge fudge to the NMEA time. Or add the suffix 'noselect' so it +is never used, just monitored. + +== Performance Tuning == + +This section is general and can be used with either ntpd or chronyd. +We'll have more to say about tuning techniques for the specific +implementations in later sections. + +The clock crystals used in consumer electronics have two properties we +are interested in: accuracy and stability. *Accuracy* is how well the +measured frequency matches the number printed on the can. *Stability* +is how well the frequency stays the same even if it isn't accurate. +(Long term aging is a third property that is interesting, but ntpd and +chrony both a use a drift history that is relatively short; thus, +this is not a significant cause of error.) + +Typical specs for oscillator packages are 20, 50, 100 ppm. That includes +everything; initial accuracy, temperature, supply voltage, aging, etc. + +With a bit of software, you can correct for the inaccuracy. ntpd and +chrony both call it *drift*. It just takes some extra low order bits +on the arithmetic doing the time calculations. In the simplest case, +if you thought you had a 100 MHz crystal, you need to change that to +something like 100.000324. The use of a PPS signal from gpsd +contributes directly to this measurement. + +Note that a low drift contributes to stability, not necessarily accuracy. + +The major source of instability is temperature. Ballpark is the drift +changes by 1 PPM per degree C. This means that the drift does not stay +constant, it may vary with a daily and yearly pattern. This is why the +value of drift the ntpd uses is calculated over a (relatively) short time. + +So how do we calculate the drift? The general idea is simple. +Measure the time offset every N seconds over a longer window of time +T, plot the graph, and fit a straight line. The slope of that line is +the drift. The units cancel out. Parts-per-million is a handy scale. + +How do you turn that handwaving description into code? One easy way +is to set N=2 and pick the right T, then run the answer through a +low pass filter. In that context, there are two competing sources of +error. If T is too small, the errors on each individual measurement +of the offset time will dominate. If T is too big, the actual drift +will change while you are measuring it. In the middle is a sweet +spot. (For an example, see <>.) + +Both ntpd and chrony use this technique; ntpd also uses a more +esoteric form of estimation called a "PLL/FLL hybrid loop". How T and N are +chosen is beyond the scope of this HOWTO and varies by implementation +and tuning parameters. + +If you turn on the right logging level ("statistics loopstats peerstats" +for ntpd, "log measurements tracking" for chronyd) , that will record +both offset, drift, and the polling interval. The ntpd stats are easy to +feed to gnuplot, see the example script in the GPSD contrib directory. +The most important value is the offset reported in the 3rd field in +loopstats and the last field in tracking.log. With gnuplot you can +compare them (after concatenating the rotated logs): + +----------------------------------------------------------------------------- +plot "tracking.log" using 7 with lines, "loopstats" using 3 with lines +----------------------------------------------------------------------------- + +While your NTP daemon (ntpd or chrony) is adjusting the polling +interval, it is assuming that the drift is not changing. It gets +confused if your drift changes abruptly, say because you started some +big chunk of work on a machine that's usually idle and that raises the +temperature. + +Your NTP daemon writes out the drift every hour or so. (Less often if +it hasn't changed much to reduce the workload on flash file systems.) +On startup, it reloads the old value. + +If you restart the daemon, it should start with a close old drift +value and quickly converge to the newer slightly different value. If +you reboot, expect it to converge to a new/different drift value and +that may take a while depending on how different the basic calibration +factors are. + +=== ARP is the sound of your server choking === + +By default ntpd and chronyd poll remote servers every 64 seconds. This +is an unfortuneate choice. Linux by default only keeps an ARP table +entry for 60 seconds, anytime thereafter it may be flushed. + +If the ARP table has flushed the entry for a remote peer or server then +when the NTP server sends a request to the remote server an entire ARP +cycle will be added to the NTP packet round trip time (RTT). This will +throw off the time measurements to servers on the local lan. + +On a RaspberryPi ARP has been shown to impact the remote offset by up to +600 uSec in some rare cases. + +The solution is the same for both ntpd and chronyd, add the "maxpoll 5" +command to any 'server" or "peer directive. This will cause the maximum +polling period to be 32 seconds, well under the 60 second ARP timeout. + +=== Watch your temperatures === + +The stability of the system clock is very temperature dependent. A one +degree change in room temperature can create 0.1 ppm of clock frequency +change. Once simple way to see the effect is to place your running +NTP server inside bubble wrap. The time will take a quick and noticeable +jump. + +If you leave your NTP server in the bubble wrap you will notice some +improved local and remote offsets. + +=== Powersaving is not your friend === + +Normally enabling power saving features is a good thing: it saves you power. +But when your CPU changes power saving modes (cstates for Intel CPUs) the +impact on PPS timing is noticeable. For some reason the NO_HZ kernel +mode has a similar bad effect on timekeeping. + +To improve your timekeeping, turn off both features on Intel CPUs by +adding this to your boot command line: + +----------------------------------------------------------------------------- +nohz=off intel_idle.max_cstate=0 +----------------------------------------------------------------------------- + +For ARM, be sure NO_HZ is off: + +----------------------------------------------------------------------------- +nohz=off +----------------------------------------------------------------------------- + +You will also need to select the 'performance' CPU governor to keep ypur +CPU set to the maximum speed for continuous usage. How you see and set +your governor will be distribution specific. The easiest way it to +recompile your kernel to only provide the performance governor. + +== NTP tuning and performance details == + +This section deals specifically with ntpd. It discusses algorithms +used by the ntpd suite to measure and correct the system time. It is not +directly applicable to chronyd, although some design considerations +may be similar. + +It is hard to optimize what you can't visualize. The easiest way to +visualize ntpd performance is with ntpviz from <>. Once you +are regularly graphing your server performance it is much easier to see +the results of changes. + +=== NTP performance tuning === + +For good time stability, you should always have at least four other +servers in your ntpd or chrony configuration besides your GPS receiver +- in case, for example, your GPS receiver is temporarily unable to achieve +satellite lock, or has an attack of temporary insanity. You can find +public NTP servers to add to your configuration at <>. + +To minimize latency variations, use the national and regional +pool domains for your country and/or nearby ones. Your ntp.conf +configuration line should probably look like this + +----------------------------------------------------------------------------- +pool us.pool.ntp.org iburst +----------------------------------------------------------------------------- + +where "us" may be replaced by one of the zone/country codes the Pool +project supports (list behind the "Global" link at <>). The +"pool" tag expands to four randomly chosen servers by default. "iburst" +implements a fast start algorithm that also weeds out bad servers. + +Note that a server can be a poor performer (what the NTP documentation +colorfully calls a "falseticker") for any of three reasons. It may be +shipping bad time, or the best routes between you and it have large +latency variations (jitter), or it may have a time-asymmetric route, +to you (that is, B-to-A time is on average very different from A-to-B +time). Asymmetric routing is the most common cause of serious +problems. + +The standard tool for tuning ntpd is "ntpq" ("NTP query program"). To +show a list of all servers declared in ntp.conf and their statistics, +invoke it with the "-p" option. On a sample system configured with 7 +servers from the NTP pool project and one PPS GPS receiver attached +via RS232, this is the output: + +------------------------------------------------------------------------ +$ ntpq -p + remote refid st t when poll reach delay offset jitter +======================================================================== +-arthur.testserv 162.23.41.56 2 u 62 64 377 5.835 -1.129 8.921 +-ntppublic.uzh.c 130.60.159.7 3 u 62 64 377 6.121 -4.102 6.336 +-smtp.irtech.ch 162.23.41.56 2 u 35 64 377 15.521 -1.677 8.678 ++time2.ethz.ch .PPS. 1 u 27 64 377 5.938 -1.713 16.404 +-callisto.mysnip 192.53.103.104 2 u 53 64 377 49.357 -0.274 5.125 +-shore.naturalne 122.135.113.81 3 u 22 64 377 14.676 -0.528 2.601 +-ntp.univ-angers 195.220.94.163 2 u 41 64 377 40.678 -1.847 13.391 ++SHM(0) .GPS. 0 l 4 64 377 0.000 34.682 7.952 +*SHM(1) .PPS. 0 l 3 64 377 0.000 -2.664 0.457 +------------------------------------------------------------------------ + +The interesting columns are "remote", "st", "reach" and "offset". + +"remote" is the name of the remote NTP server. The character in its +first column shows its current state: "-" or "x" for out-of-tolerance +servers, "+" for good servers ("truechimers"), and "*" for the one good +server currently used as the primary reference. The calculations used to +determine a server's state are outside the scope of this document; +details are available in NTPv4 RFC 5905. + +"st" shows the remote server's stratum. + +"reach" is the octal representation of the remote server's reachability. +A bit is set if the corresponding poll of the server was successful, +i.e. the server returned a reply. New poll results are shifted in from +the least significant bit; results older than 8 polls are discarded. In +the absence of network problems, this should show "377". + +"offset" shows the mean offset in the times reported between this local +host and the remote server in milliseconds. This is the value that can +be fudged with the "time1" parameter of the GPS server line in ntp.conf. +If the offset is positive, reduce the time1 value and vice versa. + +The asterisk in this example indicates that ntpd has correctly +preferred .PPS. over .GPS., as it should. If for some reason it +locks on to GPS time as a preferred source, you can add an overlarge +fudge to the NMEA time to discourage it. Or add the suffix 'noselect' +so GPS time is never used, just monitored. + +A more detailed description of the output is available at +<>. + +In order to determine the correct GPS offset, do one of the following: + +==== Peerstats-based procedure ==== + +[start=1] +. Add these lines to ntp.conf: + +----------------------------------------------------------------------------- +statsdir /var/log/ntpstats/ +statistics peerstats +filegen peerstats file peerstats type day enable +----------------------------------------------------------------------------- + +This enables logging of the peer server statistics. + +. Make sure the directory exists properly. For ntpd as root do: + +----------------------------------------------------------------------------- + # mkdir -p /var/log/ntpstats + # chown ntp:ntp /var/log/ntpstats +----------------------------------------------------------------------------- + +. Start ntpd and let it run for at least four hours. +Periodically check progress with "ntpq -p" and wait +until change has settled out. + +. Calculate the average GPS offset using this script (a copy is +included as contrib/ntpoffset in the GPSD distribution): + +----------------------------------------------------------------------------- +awk ' + /127\.127\.28\.0/ { sum += $5 * 1000; cnt++; } + END { print sum / cnt; } +' >. ntpviz generates lots of pretty graphs +and html pages. It even calculates the correct IMT offset, and other +performance metrics for you. + +===== Format of the loopstats and peerstats files ===== + +The following is incorporated from the ntpd website, see <> + +.loopstats + +Record clock discipline loop statistics. Each system clock update +appends one line to the loopstats file set: + +Example: 50935 75440.031 0.000006019 13.778 0.000351733 0.013380 6 + +|================================ +|Item |Units |Description +|50935 |MJD |date +|75440.031 |s |time past midnight (UTC) +|0.000006019 |s |clock offset +|13.778 |PPM |frequency offset +|0.000351733 |s |RMS jitter +|0.013380 |PPM |RMS frequency jitter (aka wander) +|6 |log2 s |clock discipline loop time constant +|================================= + + +.peerstats + +Record peer statistics. Each NTP packet or reference clock update +received appends one line to the peerstats file set: + +Example: 48773 10847.650 127.127.4.1 9714 -0.001605376 0.000000000 0.001424877 0.000958674 + +|================================ +|Item |Units |Description +|48773 |MJD |date +|10847.650 |s |time past midnight (UTC) +|127.127.4.1 |IP |source address +|9714 |hex |status word +|-0.001605376 |s |clock offset +|0.000000000 |s |roundtrip delay +|0.001424877 |s |dispersion +|0.000958674 |s |RMS jitter +|================================ + +===== Measurement of delay ===== + +There are three parts to measuring and correcting for the delay in +processing the 1PPS signal. + +1. Running ntpd without using the IMT (but using the 1PPS time) +2. Measuring the delay between the two messages +3. Applying the correction factor + +We assume that you have successfully integrated GPSD with ntpd already. +You should also have a decent set of NTP servers you are syncing to. + +[start=1] +. Running ntpd without IMT + +Locate the line in your ntp.conf that refers to the SHM0 segment and +append 'noselect' to it. As an example, the first two lines in the sample +above will become: + +-------------------- +server 127.127.28.0 minpoll 4 maxpoll 4 noselect +fudge 127.127.28.0 time1 0.420 refid GPS +-------------------- + +ntpd will now continue to monitor the IMT from GPSD, but not use it +for its clock selection algorithm. It will still write out statistics to +the peerstats file. Once ntpd is stable (a few hours or so), we can +process the peerstats file. + +. Measuring the delay between the two messages + +From the 'peerstats' file, extract the lines corresponding to +127.127.28.0 + +----------- +grep 127.127.28.0 peerstats > peerstats.shm +----------- + +You can now examine the offset and jitter of the IMT. <> +suggests the following gnuplot fragment (you will need to set output +options before plotting). + +---------------- + set term gif + set output "fudge.gif" +---------------- + +If your gnuplot has X11 support, and you do not wish to save the plot, +the above may not be required. Use: + +--------------- + set term x11 +--------------- + +Now plot the GPSD shared memory clock deviations from the system +clock. (You will get the GPSD shared memory clock fudge value +estimate from this data when NTP has converged to your +satisfaction.) + +------------------ + gnuplot> plot "peerstats.shm" using ($2):($5):($8) with yerrorbars + gnuplot> replot "peerstats.shm" using ($2):($5) with lines +------------------ + +. Applying the correction factor + +By examining the plot generated above, you should be able to estimate +the offset between the 1PPS time and the GPS time. + +If, for example, your estimate of the offset is -0.32s, your time1 fudge +value will be '0.32'. Note the change of sign. + +=== Pollling Interval === + +ntpd seems to better use a PPS refclock when the polling interval is +as small as possible. The ntpd default minpoll is 6, and can be set to +as low as 4. NTPsec versions 0.9.5 and above of ntpd allow you to +set minpoll and maxpoll as low as 0. Changing minpoll from 4 to 0 may +reduce your PPS jitter by over a factor of 4. + +----------------------------------------------------------------------------- +server 127.127.28.1 minpoll 0 maxpoll 0 prefer +----------------------------------------------------------------------------- + +== Chrony performance tuning + +The easiest way to determine the offset with chronyd is probably to +configure the source whose offset should be measured with the noselect +option and a long poll, let chronyd run for at least 4 hours and +observe the offset reported in the chronyc sourcestats output. If the +offset is unstable, wait longer. For example: + +SHM 0 configured as: +refclock SHM 0 poll 8 filter 1000 noselect + +----------------------------------------------------------------------------- +# chronyc sourcestats +210 Number of sources = 6 +Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev +============================================================================== +SHM0 21 9 85m 4.278 4.713 +495ms 8896us +SHM1 20 8 307 0.000 0.002 +0ns 202ns +mort.cihar.com 21 8 72m 0.148 0.798 +668us 490us +vps2.martinpoljak.net 6 4 17m -53.200 141.596 -24ms 15ms +ntp1.kajot.cz 25 16 91m -0.774 1.494 -11ms 1859us +ntp1.karneval.cz 17 10 89m 0.127 0.539 -4131us 574us +----------------------------------------------------------------------------- + +In this case (Garmin 18x) the offset specified in the config for the +SHM 0 source should be around 0.495. + +//FIXME: What more can we say about chronyd tuning? + +== Providing local NTP service using PTP == + +By now if you have a good serial PPS signal your local clock should +have jitter on the order of 1 uSec. You do not want the hassle of +placing a GPS receiver on each of your local computers. So you +install chrony or ntp on your other hosts and configure them to use +your NTP PPS server as their local server. + +With your best setup on a lightly loaded GigE network you find that your +NTP clients have jitter on the order of 150 uSec, or 150 times worse +than your master. Bummer, you want to do much better, so you look to +the Precision Time Protocol <> for help. PTP is also known as IEEE +1588. + +With PTP you can easily synchronize NTP hosts to 5 uSec with some +generic NIC hardware and newer Linux kernels. Some of the Ethernet +drivers have been modified to time stamp network packets when sending and +receiving. This is done with the new SO_TIMESTAMPING socket option. No +hardware support is required. + +A more recent addition is PTP Hardware Clock (PHC) support. This requires +hardware support in the NIC. + +Software timestamping is more mature, available on more NICs, and almost +as accurate as hardware timestamping. Try it first. This HOWTO will +build on those results. + +One final wrinkle before proceeding with PTP. Ethernet ports have +something called <> (IEEE 802.3az). Percentage wise EEE can save +50% of the Ethernet energy needs. Sadly this is 50% of an already small +energy usage. Only important in large data centers. EEE can be very +disruptive to timekeeping. Up to almost 1 Sec of errors in offset, +wander and jitter. To see if you have EEE enabled, and then turn it +off: + +----------------------------------------------------------------------------- +# ethtool --show-eee eth0 +EEE Settings for eth0: + EEE status: enabled - inactive + Tx LPI: 0 (us) + Supported EEE link modes: 100baseT/Full + 1000baseT/Full + Advertised EEE link modes: 100baseT/Full + 1000baseT/Full + Link partner advertised EEE link modes: Not reported +# ethtool --set-eee eth0 eee off +# ethtool --show-eee eth0 +EEE Settings for eth1: + EEE status: disabled + Tx LPI: disabled + Supported EEE link modes: 100baseT/Full + 1000baseT/Full + Advertised EEE link modes: Not reported + Link partner advertised EEE link modes: Not reported +----------------------------------------------------------------------------- + +=== PTP with software timestamping === + +To start you need to verify that your running Linux kernel configuration +includes these two lines, or the same with "y" replaced by "m" to enable +the drivers as modules: + +----------------------------------------------------------------------------- +CONFIG_NETWORK_PHY_TIMESTAMPING=y +PTP_1588_CLOCK=y +----------------------------------------------------------------------------- + +Then you need to verify that your Ethernet driver supports PTP +by running this command as root: + +----------------------------------------------------------------------------- +# ethtool -T eth0 | fgrep SOFTWARE + software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE) + software-receive (SOF_TIMESTAMPING_RX_SOFTWARE) + software-system-clock (SOF_TIMESTAMPING_SOFTWARE) +----------------------------------------------------------------------------- + +If the result includes those three lines then you have support for +software PTP timestamping. We will leave hardware timestamping +for later. + +Next you will need the <> package, just follow the simple +instructions on their web page to download, compile and install on your +NTP server and its slaves. Be sure to also follow their instructions on +how to configure your Linux kernel. + +In this setup we will just use the ptp4l program. This program measures +the delay and offset between a master and slaves and shares that information +with chronyd or ntpd using an SHM. Since gpsd also uses SHM be very careful +not to have the two SHM servers stepping on the same shmid. + +If you are using ntpd, then add the last three lines below to your +master ntp.conf file to configure the SHM. + +----------------------------------------------------------------------------- +# GPS Serial data reference (NTP0) +server 127.127.28.0 +fudge 127.127.28.0 time1 0.9999 refid GPS + +# GPS PPS reference (NTP1) +server 127.127.28.1 prefer +fudge 127.127.28.1 refid PPS + +# local PTP reference (NTP2) +server 127.127.28.2 +fudge 127.127.28.2 refid PTP +----------------------------------------------------------------------------- + +If you are using chronyd, then add the last one line below to your +master chronyd.conf file to configure the SHM. + +----------------------------------------------------------------------------- +refclock SHM 0 refid GPS precision 1e-1 offset 0.9999 delay 0.2 +refclock SHM 1 refid PPS precision 1e-9 +refclock SHM 2 refid PTP precision 1e-9 +----------------------------------------------------------------------------- + +To configure the master ptp4l, create a new file +/usr/local/etc/ptp4l.conf with these contents: + +----------------------------------------------------------------------------- +[global] +# only syslog every 1024 seconds +summary_interval 10 + +# send to to chronyd/ntpd using SHM 2 +clock_servo ntpshm +ntpshm_segment 2 + +# set our priority high since we have PPS +priority1 10 +priority2 10 + +[eth0] +----------------------------------------------------------------------------- + +Now as root on the master, start the ptp4l daemon: + +----------------------------------------------------------------------------- +# ethtool --set-eee eth0 eee off +# ptp4l -S -f /usr/local/etc/ptp4l.conf & +----------------------------------------------------------------------------- + +Configuration of the master server is now complete. Now to configure +the slaves. If the slaves also have PPS then configure them as masters. +Otherwise you will stomp on your SHMs. + +If you are using ntpd, then add the last three lines below to your +master ntp.conf file to configure your one and only SHM. + +----------------------------------------------------------------------------- +# local PTP reference (NTP0) +server 127.127.28.0 +fudge 127.127.28.0 refid PTP +----------------------------------------------------------------------------- + +If you are using chronyd, then add the one line below to your master +chronyd.conf file to configure your one and only SHM. + +----------------------------------------------------------------------------- +refclock SHM 0 refid PTP precision 1e-9 +----------------------------------------------------------------------------- + +To configure the slave ptp4l, create a new file +/usr/local/etc/ptp4l.conf with these contents: + +----------------------------------------------------------------------------- +[global] +# only syslog every 1024 seconds +summary_interval 10 + +# send to to chronyd/ntpd using SHM 0 +clock_servo ntpshm +ntpshm_segment 0 + +[eth0] +----------------------------------------------------------------------------- + +Now as root on the slave, as with the master, turn off EEE and start the +ptp4l daemon: + +----------------------------------------------------------------------------- +# ethtool --set-eee eth0 eee off +# ptp4l -S -f /usr/local/etc/ptp4l.conf & +----------------------------------------------------------------------------- + +Configuration of the slave server is now complete. Follow the earlier +procedures for checking the jitter on the SHM on the slaves. Give it +a few hours to settle and your hosts will now be synced to around 5 uSec. + +=== PTP with hardware timestamping === + +Some NICs requires two additional kernel options. Just in case, verify +that your running Linux kernel configuration includes these lines, or +the same with "y" replaced by "m" to enable the drivers as modules: + +----------------------------------------------------------------------------- +CONFIG_DP83640_PHY=y +CONFIG_PTP_1588_CLOCK_PCH=y +----------------------------------------------------------------------------- + +Then you need to verify that your Ethernet driver supports PTP +by running ethtool as root and verify at least the following lines are +present in the output: + +----------------------------------------------------------------------------- +# ethtool -T eth0 + hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE) + hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE) + all (HWTSTAMP_FILTER_ALL) +----------------------------------------------------------------------------- + +Your NIC may have more features, and your driver may support them for +better results. + +In the software timestamping above the ptp4l program took care of all steps to +determine the slave offset from the master and feeding that to a a SHM for +ntpd or chronyd to use.o + +In hardware timestamping mode ptp4l will continue to perform most of +the work. An additional program, phc2sys, will take over the duties of +reading the hardware timestamps from the NIC, computing the offset, and +feeding that to the SHM. + +phc2sys will use the SHM exactly as ptp4l did previously so no +change is required to your ntpd or chronyd configuration. + +To keep things simple, for now, we will not touch the already configured +and working software timestamping master server. We will proceed to +configure a slave. + +To configure the slave ptp4l, edit your /usr/local/etc/ptp4l.conf +to remove the ntpshm options: + +----------------------------------------------------------------------------- +[global] +# only syslog every 1024 seconds +summary_interval 10 + +clock_servo linreg + +[eth0] +----------------------------------------------------------------------------- + +Now as root on the slave, as with the master, turn off EEE and start the +ptp4l daemon: + +----------------------------------------------------------------------------- +# ethtool --set-eee eth0 eee off +# ptp4l -H -f /usr/local/etc/ptp4l.conf & +# sleep 3 +# phc2sys -a -r -E ntpshm -m -M 0 & +----------------------------------------------------------------------------- + + +Configuration of the slave server is now complete. Follow the earlier +procedures for checking the jitter on the SHM on the slaves. + +Sadly, theory and practice diverge here. I have never succeeded in +making hardware timestamping work. I have successfully trashed my +host system clock. Tread carefully. If you make progress please +pass on some clue. + +== Providing public NTP service == + +<> has good advice on things to be sure you have done - and +are ready to do - before becoming a public server. One detail it +doesn't mention is that you'll need to un-firewall UDP port 123. The +NTP protocol does not use TCP, so no need to unblock TCP port 123. + +If and when you are ready to go public, see <>. + +== Acknowledgments == +Beat Bolli wrote much of the section on NTP +performance tuning. Hal Murray wrote +much of the section on NTP working and performance details. +Sanjeev Gupta assisted with editing. +Shawn Kohlsmith tweaked the Bibliography. +Jaap Winius cleaned up some terminology. + +The loopstats-based tuning procedure for ntpd was drafted by Sanjeev +Gupta , based on discussions on the GPSD list +<> in Oct and Nov 2013. Code examples are based on work by +Andy Walls . A copy of the original +email can be found at <>. A thorough review was contributed +by Jaap Winius . + +== References == + +[bibliography] + +- [[[TIME-INTRO]]] link:time-service-intro.html[Introduction to Time Service] + +- [[[WIKI-NTP]]] http://en.wikipedia.org/wiki/Network_Time_Protocol[Network Time Protocol] + +- [[[NTP-FAQ]]] http://www.ntp.org/ntpfaq/[NTP FAQ] + +- [[[SIRF-WOBBLE]]] http://www.megapathdsl.net/~hmurray/ntp/GPSSiRF-off.gif[Peer Offset of SiRF units] + +- [[[RFC-2783]]] http://tools.ietf.org/html/rfc2783[RFC 2783] + +- [[[RFC-5905]]] http://tools.ietf.org/html/rfc5905[RFC 5905] + +- [[[MACX-1]]] https://www.etsy.com/listing/280336400/navisys-gr-601w-u-blox-6-macx-1-usb-gps[Navisys GR-601W u-blox-6 "Macx-1" USB GPS receiver] + +- [[[CHRONY-COMPARE]]] http://chrony.tuxfamily.org/manual.html#Comparison-with-ntpd[ntpd (comparison with chrony)] + +- [[[CHRONYDEFAULT]]] https://lists.fedoraproject.org/pipermail/devel/2010-May/135679.html + +- [[[HARDWARE]]] http://catb.org/gpsd/hardware.html[Compatible Hardware] + +- [[[UBLOX-TIMING]]] http://www.u-blox.com/images/downloads/Product_Docs/Timing_AppNote_%28GPS.G6-X-11007%29.pdf[GPS-based timing considerations with u-blox 6 receivers] + +- [[[RPI]]] http://www.satsignal.eu/ntp/Raspberry-Pi-NTP.html[The Raspberry Pi as a Stratum-1 NTP Server] + +- [[[NTP.ORG]]] http://www.ntp.org/[Home of the Network Time Protocol project] + +- [[[NTPSEC.ORG]]] http://www.ntpsec.org/[Wecome to NTPsec] + +- [[[USE-POOL]]] http://www.pool.ntp.org/en/use.html[How do I use pool.ntp.org?] + +- [[[CVE-2009-3563]]] http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2009-3563 + +- [[[CHRONY]]] http://chrony.tuxfamily.org/[Chrony Home] + +- [[[CHRONY-MAN]]] http://chrony.tuxfamily.org/manual.html + +- [[[ADEV-PLOT]]] http://www.leapsecond.com/pages/adev-avg/[Allan deviation and Averaging] + +- [[[ZONES]]] http://www.pool.ntp.org/zone + +- [[[NTPQ-OUTPUT]]] http://nlug.ml1.co.uk/2012/01/ntpq-p-output/831[ntpq output description] + +- [[[JOIN-POOL]]] http://www.pool.ntp.org/en/join.html[How do I join pool.ntp.org?] + +- [[[ANDY-POST]]] http://lists.gnu.org/archive/html/gpsd-dev/2013-10/msg00152.html[Clarifications needed for the time-service HOWTO] + +- [[[NTP-MONOPT]]] http://www.eecis.udel.edu/~mills/ntp/html/monopt.html[NTP Monitoring] + +- [[[GPSD-LIST]]]http://lists.gnu.org/archive/html/gpsd-dev[gpsd-dev Archives] + +- [[[PTP]]] http://www.nist.gov/el/isd/ieee/ieee1588.cfm/[PTP] + +- [[[LINUX-PTP]]] http://linuxptp.sourceforge.net/[Linux PTP] + +- [[[EEE]]] https://en.wikipedia.org/wiki/Energy-Efficient_Ethernet[Energy-Efficient Ethernet] + +- [[[LVC]]] http://www.rjsystems.nl/en/2100-ntpd-garmin-gps-18-lvc-gpsd.php + +== Changelog == + +1.1, Nov 2013:: + Initial release. + +1.2, Aug 2014:: + Note that NetBSD now has PPS support. + +1.3, Aug 2014:: + Add a note about the GR-601W. + +1.4, Dec 2014:: + Cleaned up Bibliography + +2.0, Feb 2015:: + More about troubleshooting PPS delivery. Folded in Sanjeev + Gupta's Calibration Howto describing the loopstats-based + procedure. Added preliminary information on PTP. + +2.1 Mar 2015:: + More on PTP. Added link to Jaap Winius's page on GPS-18 setup. + +2.2 Mar 2015:: + Detailed explanation of NTP has moved to a new page, + link:time-service-intro.html[Introduction to Time Service]. + +2.3 Mar 2015:: + Use the NTP accuracy estimate from RFC 5905. + +2.4 Mar 2015:: + Removed some typos, corrected formatting, and minor changes. + A bit more specificity about root vs. non-root. + +2.5 Apr 2016:: + Note the existence of the GR-701W. + +2.6 May 2016:: + New section on GPS time. Note the existence of the GR-801W. + Describe the special timeserver build of GPSD. Recommend NTPsec. + Add Macx-1 link. + Add sections on ARP and temperature problems + +2.7 June 2016 + Add section on avoiding power saving. + +2.8 July 2016 + Mention required version of gpsd + Fix Typos. + +2.9 August 2016 + Fix typos. + +2.10 September 2016 + Mention ntpviz + Recommend minpoll=maxpoll=0 for PPS refclocks + Recommend NTPsec. + +// end diff --git a/www/gpsd-time-service-howto.txt b/www/gpsd-time-service-howto.txt deleted file mode 100644 index a3204d65..00000000 --- a/www/gpsd-time-service-howto.txt +++ /dev/null @@ -1,1867 +0,0 @@ -= GPSD Time Service HOWTO = -:description: How to set up an NTP Stratum 1 server using GPSD. -:keywords: time, GPSD, NTP, time, precision, 1PPS, PPS, stratum, jitter -Gary E. Miller , Eric S. Raymond -v2.10, Sep 2016 - -This document is mastered in asciidoc format. If you are reading it in HTML, -you can find the original at the GPSD project website. - -== Introduction == - -GPSD, NTP and a GPS receiver supplying 1PPS (one pulse-per-second) -output can be used to set up a high-quality NTP time server. This -HOWTO explains the method and various options you have in setting it -up. - -Here is the quick-start sequence. The rest of this document goes -into more detail about the steps. - -1. Ensure that gpsd and either ntpd or chronyd are installed on your - system. (Both gpsd and ntpd are preinstalled in many stock Linux - distributions; chronyd is normally not.) You don't have to choose - which to use yet if you have easy access to both, but knowing which - alternatives are readily available to you is a good place to start. - -2. Verify that your gpsd version is at least 3.17. Many problems are - caused by the use of old versions. When in doubt, reinstall - gpsd from the upstream source. Many distributions ship old - and/or broken versions of gpsd. - -3. Connect a PPS-capable GPS receiver to one of your serial or USB - ports. A random cheap consumer-grade GPS receiver won't do; you - may have to do some hunting to find a usable one. - -4. Check that it actually emits PPS by pointing GPSD's gpsmon utility - at the port. If it has a good (3D-mode) fix, lines marked "PPS" - should scroll by in the packet-logging window. A new device out of - the box may take up to 30 minutes for the first 3D fix. If gpsmon - shows a 3D fix, but does not show PPS lines, try running ppscheck. - -5. If you persistently fail to get live PPS, (a) you may have a - skyview problem, (b) you may have a cabling problem, (c) your GPS - may not support PPS, (d) you may have a gpsd or kernel configuration - problem, (e) you may have a device problem, (e) there may be a bug - in the core GPSD code used by gpsmon. These are listed in roughly - decreasing probability. Troubleshoot appropriately. - -6. Edit your ntpd or chronyd configuration to tell your NTP daemon to - listen for time hints. (This step is somewhat tricky.) - -7. Start up gpsd. If you are using ntpd, you can use ipcrm(1) to check that - verify that the shared-memory segment that gpsd and ntpd want to - use to communicate has been attached; or you can impatiently skip - to the next step and look for the segment only if that fails. - -8. Use ntpq or the chronyc sources command to verify that your device - is feeding time corrections to your NTP daemon. - -9. (Optional and challenging.) Hand-tune your installation for the - best possible performance. - -This document does not attempt to explain all the intricacies of time -service; it is focused on practical advice for one specific deployment -case. There is an introduction <> to basic concepts and -terminology for those new to time service. An overview of the NTP -protocols can be found at <>, and the official NTP FAQ -<> is probably as gentle an introduction to the NTP reference -implementation as presently exists. - -We encourage others to contribute additions and corrections. - -.Units table -|==================================================== -| nSec | nanoSecond | 1/1,000,000,000 of a second -| uSec | microSecond | 1/1,000,000 of a second -| mSec | milliSecond | 1/1,000 of a second -|==================================================== - -There are a few important terms we need to define up front. *Latency* -is delay from a time measurement until a report on it arrives where it -is needed. *Jitter* is short-term variation in latency. *Wobble* is a -jitter-like variation that is long compared to typical measurement -periods. *Accuracy* is the traceable offset from 'true' time as -defined by a national standard institute. - -A good analogy to jitter vs wobble is changes in sea level on a beach. -Jitter is caused by wave action, wobble is the daily effect of tides. -For a time server, the most common causes of wobble are varying GPS -satellite geometries and the effect of daily temperature variations on -the oscillators in your equipment. - -== NTP with GPSD == - -See <> for a technical description of how NTP corrects -your computer's clock against wobble. For purposes of this how-to, the -important concepts to take way are those of time strata, servers, and -reference clocks. - -Ordinary NTP client computers are normally configured to get time from -one or more Stratum 2 (or less commonly Stratum 3) NTP -servers. However, with GPSD and a suitable GPS receiver, you can easily -condition your clock to higher accuracy than what you get from typical -Stratum 2; with a little effort, you can do better than you can get -from most public Stratum 1 servers. - -You can then make your high-quality time available to other systems on -your network, or even run a public NTP server. Anyone can do this; -there is no official authority, and any NTP client may choose to use -your host as a server by requesting time from it. The time-service -network is self-regulating, with NTP daemons constantly pruning -statistical outliers so the timebase cannot be accidentally or -deliberately compromised. - -In fact many public and widely-trusted Stratum 1 servers use GPS -receivers as their reference clocks, and a significant fraction of -those use GPSD in the way we will describe here. - -== GPS time == - -The way time is shipped from GPS satellites causes problems to -beware of in certain edge cases. - -Date and time in GPS is represented as number of weeks from the start -of zero second of 6 January 1980, plus number of seconds into the -week. GPS time is *not* leap-second corrected, though satellites also -broadcast a current leap-second correction which is updated on -six-month boundaries according to rotational bulletins issued by the -International Earth Rotation and Reference Systems Service (IERS). - -The leap-second correction is only included in the multiplexed satellite -subframe broadcast, once every 12.5 minutes. While the satellites do -notify GPSes of upcoming leap-seconds, this notification is not -necessarily processed correctly on consumer-grade devices, and may not -be available at all when a GPS receiver has just cold-booted. Thus, -reported UTC time may be slightly inaccurate between a cold boot or leap -second and the following subframe broadcast. - -GPS date and time are subject to a rollover problem in the 10-bit week -number counter, which will re-zero every 1024 weeks (roughly every 19.6 -years). The last rollover (and the first since GPS went live in 1980) -was in Aug-1999; the next will fall in Apr-2019. The new "CNAV" data -format extends the week number to 13 bits, with the first rollover -occurring in Jan-2137, but this is only used with some newly added GPS -signals, and is unlikely to be usable in most consumer-grade receivers -prior to the 2019 rollover. - -For accurate time reporting, therefore, a GPS requires a supplemental -time references sufficient to identify the current rollover period, -e.g. accurate to within 512 weeks. Many GPSes have a wired-in (and -undocumented) assumption about the UTC time of the last rollover and -will thus report incorrect times outside the rollover period they were -designed in. - -For accurate time service via GPSD, you require three things: - -* A GPS made since the last rollover, so its hidden assumption about - the epoch will be correct. - -* Enough time elapsed since a cold boot or IERS leap-second adjustment - for the current leap-second to get update. - -* A GPS that properly handles leap-second adjustments. Anything - based on a u-blox from v6 onward should be good; the status of - SiRFs is unknown and doubtful. - -== 1PPS quality issues == - -GPSD is useful for precision time service because it can use the 1PPS -pulse delivered by some GPS receivers to discipline (correct) a local -NTP instance. - -It's tempting to think one could use a GPS receiver for time service -just by timestamping the arrival of the first character in the report -on each fix and correcting for a relatively small fixed latency -composed of fix-processing and RS232 transmission time. - -At one character per ten bits (counting framing and stopbits) a -9600-bps serial link introduces about a mSec of latency *per -character*; furthermore, your kernel will normally delay delivery -of characters to your application until the next timer tick, about -every 4 mSec in modern kernels. Both USB and RS232 will incur that -approximately 5mSec-per-char latency overhead. You'll have to deal -with this latency even on chips like the Venus 6 that claim the -beginning of their reporting burst is synced to PPS. (Such claims are -not always reliable, in any case.) - -Unfortunately, fix reports are also delayed in the receiver and on -the link by as much as several hundred mSec, and this delay is not -constant. This latency varies (wobbles) throughout the day. It may be -stable to 10 mSec for hours and then jump by 200mSec. Under these -circumstances you can't expect accuracy to UTC much better than 1 -second from this method. - -For example: SiRF receivers, the make currently most popular in -consumer-grade GPS receivers, exhibit a wobble of about 170mSec in the -offset between actual top-of-second and the transmission of the first -sentence in each reporting cycle. You can see this graphed at -<>. - -To get accurate time, then, the in-band fix report from the GPS -receiver needs to be supplemented with an out-of-band signal that has -a low and constant or near-constant latency with respect to the time -of of the fix. GPS satellites deliver a top-of-GPS-second -notification that is nominally accurate to 50nSec; in capable GPS -receivers that becomes the 1PPS signal. - -1PPS-capable GPS receivers use an RS-232 control line to ship the 1PPS -edge of second to the host system (usually Carrier Detect or Ring -Indicator; GPSD will quietly accept either). Satellite top-of-second -loses some accuracy on the way down due mainly to variable delays in -the ionosphere; processing overhead in the GPS receiver itself adds a -bit more latency, and your local host detecting that pulse adds still -more latency and jitter. But it's still often accurate to on the -order of 1 uSec. - -Under most Unixes there are two ways to watch 1PPS; Kernel PPS (KPPS) -and plain PPS latching. KPPS is an implementation of RFC 2783 <>. -Plain PPS just references the pulse to the system clock as -measured in user space. These have different error budgets. - -Kernel PPS uses a kernel function to accurately timestamp the status -change on the PPS line. Plain PPS has the kernel wake up the GPSD PPS -thread and then the PPS thread reads the current system clock. As -noted in the GPSD code, having the kernel do the time stamp yields -lower latency and less jitter. Both methods have accuracy degraded by -interrupt-processing latency in the kernel serial layer, but plain -PPS incurs additional context-switching overhead that KPPS does not. - -With KPPS it is very doable to get the system clock stable to ±1 -uSec. Otherwise you are lucky to get ±5 uSec, and there will be -about 20uSec of jitter. All these figures were observed on -plain-vanilla x86 PCs with clock speeds in the 2GHz range. - -All the previous figures assume you're using PPS delivered over RS232. -USB GPS receivers that deliver 1PPS are rare, but do exist. Notably, -there's the Navisys GR-601W/GR-701W/GR-801W <>. In case these devices go -out of production it's worth noting that they are a trivial -modification of the stock two-chip-on-a-miniboard -commodity-GPS-receiver design of engine plus USB-to-serial adapter; -the GR-[678]01W wires a u-blox 6/7/8 to a Prolific Logic PL23203. To -get 1PPS out, this design just wires the 1PPS pin from the GPS engine -to the Carrier Detect pin on the USB adapter. (This is known as the -"Macx-1 mod".) - -With this design, 1PPS from the engine will turn into a USB event that -becomes visible to the host system (and GPSD) the next time the USB -device is polled. USB 1.1 polls 1024 slots every second. Each slot is -polled in the same order every second. When a device is added it is -assigned to one of those 1024 polling slots. It should then be clear -that the accuracy of a USB 1.1 connected GPS receiver would be about 1 -mSec. - -As of mid-2016 no USB GPS receiver we know of implements the higher -polling-rate options in USB 2 and 3 or the interrupt capability in USB -3. When one does, and if it has the Macx-1 mod, higher USB accuracy -will ensue. - -.Summary of typical accuracy -|===================================================== -| GPS atomic clock | ±50nSec -| KPPS | ±1uSec -| PPS | ±5uSec -| USB 1.1 poll interval | ±1mSec -| USB 2.0 poll interval | ±100μSec (100000 nSec) -| Network NTP time | ~±30mSec footnote:[RFC5905 says "a few tens of milliseconds", but asymmetric routing can produce 100mSec offset] -|===================================================== - -Observed variations from the typical figure increase towards the bottom -of the table. Notably, a heavily loaded host system can reduce PPS -accuracy further, though not KPPS accuracy except in the most extreme -cases. The USB poll interval tends to be very stable (relative to its -1mSec or 100μSec base). - -Network NTP time accuracy can be degraded below RFC5905's "a few tens -of milliseconds" by a number of factors. Almost all have more to do -with the quality of your Internet connection to your servers than with -the time accuracy of the servers themselves. Some negatives: - -* Having a cable modem. That is, as opposed to DSL or optical fiber, which - tend to have less variable latencies. - -* Path delay asymmetries due to peering policy. These can confuse - NTP's reconciliation algorithms. - -With these factors in play, worst-case error can reach up to -±100mSec. Fortunately, errors of over ±100mSec are -unusual and should occur only if all your network routes to servers -have serious problems. - -== Software Prerequisites == - -If your kernel provides the RFC 2783 KPPS (kernel PPS) API, gpsd will -use that for extra accuracy. Many Linux distributions have a package -called "pps-tools" that will install KPPS support and the timepps.h -header file. We recommend you do that. If your kernel is built in -the normal modular way, this package installation will suffice. - -=== Building gpsd == - -A normal gpsd build includes support for interpreting 1PPS pulses that -is mostly autoconfiguring and requires no special setup. - -You can build a version stripped to the mimimum configuration required -for time service. This reduces the size of the binary and may be -helpful on embedded systems or for SBCs like the Raspberry Pi, Odroid, -or BeagleBone. Also, when gpsd is built in this way, the -n (nowait) -option is forced; gpsd opens its command-line devices immediately on -startup. - -Do it like this: - ------------------------------------------------------------------------------ -scons timeservice=yes nmea0183=yes fixed_port_speed=9600 fixed_stop_bits=1 ------------------------------------------------------------------------------ - -You may substitute a different GPS (e.g. "ublox" or "sirf"), You can -also fix the serial parameters to avoid autobauding lag; the code -assumes 8 bit bytes, so the above locks the daemon to 9600 8N1. Besides -the daemon, this also builds gpsmon and ntpshmmon. - -Otherwise, make sure the build is with pps=yes and ntpshm=yes (the -default). The command "gpsd -L" should indicate that time-service -features and PPS are enabled. - -=== Kernel support === - -If you are scratch-building a Linux kernel, the configuration -must include either these two lines, or the same with "y" replaced -by "m" to enable the drivers as modules: - ------------------------------------------------------------------------------ -CONFIG_PPS=y -CONFIG_PPS_CLIENT_LDISC=y ------------------------------------------------------------------------------ - -Some embedded systems, like the Raspberry Pi, detect PPS on a GPIO -line instead of an a serial port line. For those systems you will -also need these two lines: - ------------------------------------------------------------------------------ -CONFIG_PPS_CLIENT_GPIO=y -CONFIG_GPIO_SYSFS=y ------------------------------------------------------------------------------ - -Your Linux distribution may ship a file /boot/config-XXX (where XXX is -the name of a kernel) or one called /proc/config.gz (for the running -kernel). This will have a list of the configuration options that were -used to build the kernel. You can check if the above options are -set. Usually they will be set to "m", which is sufficient. - -NetBSD has included the RFC2783 Pulse Per Second API for real serial -ports by default since 1998, and it works with ntpd. NetBSD 7 -(forthcoming) includes RFC2783 support for USB-serial devices, and -this works (with ntpd) with the GR-601W/GR-701W/GR-801W. However, -gpsd's code interacts badly with the NetBSD implementation, and gpsd's -support for RFC2783 PPS does not yet work on NetBSD (for serial or -USB). - -Other OSes have different ways to enable KPPS in their kernels. -When we learn what those are, we'll document them or point -at references. - -=== Time service daemon === - -You will need to have either ntpd or chrony installed. If you are -running a Unix variant with a package system, the packages will -probably be named 'ntp' (or 'ntpsec') and either 'chrony' or 'chronyd'. - -Between ntp and chrony, ntp is the older and more popular choice - -thus, the one with the best-established peer community if you need -help in unusual situations. On the other hand, chrony has a -reputation for being easier to set up and configure, and is better in -situations where your machine has to be disconnected from the Internet -for long enough periods of time for the clock to drift significantly. - -ntpd and chrony have differing philosophies, with ntpd more interested -in deriving consensus time from multiple sources while chrony tries to -identify a single best source and track it closely. - -A feature comparison, part of the chrony documentation, is at -<>. An informative email thread about the differences -is <>. If you don't already know enough about time -service to have a preference, the functional differences between them -are unlikely to be significant to you; flip a coin. - -If you choose ntpd, it's best to go with the NTPsec version rather -than legacy ntpd. (As of September 2016 NTPsec is not yet generally -available in binary package form. You will have to build it from -source.) NTPsec shares some maintainers with GPSD, and has some -significant improvements in security and performance. - -== Choice of Hardware == - -To get 1PPS to your NTP daemon, you first need to get it from a -PPS-capable GPS receiver. As of early 2015 this means either the -previously mentioned GR devices or a serial GPS receiver with 1PPS. - -You can find 1PPS-capable devices supported by GPSD at <>. -Note that the most popular consumer-grade GPS receivers do not usually -deliver 1PPS through USB or even RS232. The usual run of cheap GPS -mice won't do. In general, you can't use a USB device for time -service unless you know it has the Macx-1 mod. - -In the past, the RS232 variant of the Garmin GPS-18 has been very -commonly used for time service (see <> for a typical setup very -well described). While it is still a respectable choice, newer -devices have better sensitivity and signal discrimination. This makes -them superior for indoor use as time sources. - -In general, use a GPS receiver with an RS232 interface for time -service if you can. The GR-601W was designed (by one of the authors, -as it happens) for deployment with commodity TCP/IP routers that only -have USB ports. RS232 is more fiddly to set up (with older devices -like the GPS-18 you may even have to make your own cables) but it can -deliver three orders of magnitude better accuracy and repeatability - -enough to meet prevailing standards for a public Stratum 1 server. - -Among newer receiver designs the authors found the the u-blox line of -receivers used in the GR-[678]01W to be particularly good. Very -detailed information on its timing performance can be found at -<>. One of us (Raymond) has recent experience with an -eval kit, the EVK 6H-0-001, that would make an excellent Stratum 0 -device. - -Both the EVK 6H and GR-601W are built around the LEA-6H module, which -is a relatively inexpensive but high-quality navigation GPS -receiver. We make a note of this because u-blox also has a specialized -timing variant, the LEA 6T, which would probably be overkill for an -NTP server. (The 6T does have the virtue that you could probably get a -good fix from one satellite in view once it knows its location, but -the part is expensive and difficult to find.) - -Unfortunately as of early 2015 the LEA-6H is still hard to find in a -packaged RS232 version, as opposed to a bare OEM module exporting TTL -levels or an eval kit like the EVK 6H-0-001 costing upwards of -US$300. Search the web; you may find a here-today-gone-tomorrow offer -on alibaba.com or somewhere similar. - -The LEA-6T, and some other higher-end GPS receivers (but not the -LEA-6H) have a stationary mode which, after you initialize it with the -device's location, can deliver time service with only one good -satellite lock (as opposed to the three required for a fix in its -normal mode). For most reliable service we recommend using stationary -mode if your device has it. GPSD tools don't yet directly support -this, but that capability may be added in a future release. - -The design of your host system can also affect time quality. The -±5uSec error bound quoted above is for a dual-core or better -system with clock in the 2GHz range on which the OS can schedule the -long-running PPS thread in GPSD on an otherwise mostly unused -processor (the Linux scheduler, in particular, will do this). On a -single-core system, contention with other processes can pile -on several additional microseconds of error. - -If you are super-serious about your time-nuttery, you may want to look -into the newest generation of dedicated Stratum 1 microservers being -built out of open-source SBCs like the Raspberry Pi and Beaglebone, or -sometimes with fully custom designs. A representative build is well -described at <>. - -These microserver designs avoid load-induced jitter by being fully -dedicated to NTP service. They are small, low-powered devices and -often surprisingly inexpensive, as in costing less than US$100. They -tend to favor the LEA-6H, and many of them use preinstalled GPSD on -board. - -== Enabling PPS == - -You can determine whether your GPS receiver emits 1PPS, and gpsd is -detecting it, by running the gpsmon utility (giving it the GPS -receiver's serial-device path as argument). Watch for lines of dashes -marked 'PPS' in the packet-logging window; for most GPS receiver types -there will also be a "PPS offset:" field in the data panels above -showing the delta between PPS and your local clock. - -If you don't have gpsmon available, or you don't see PPS lines in it, -you can run ppscheck. As a last resort you can gpsd at -D 5 and watch -for PPS state change messages in the logfile. - -If you don't see evidence of incoming PPS, here are some trouble -sources to check: - -1. The skyview of your GPS receiver may be poor. Suspect this if, - when you watch it with gpsmon, it wanders in and out of having a - good 3D fix. Unfortunately, the only fix for this is to re-site - your GPS where it can see more sky; fortunately, this is not as - common a problem as it used to be, because modern receivers are - often capable of getting a solid fix indoors. - -2. If you are using an RS232 cable, examine it suspiciously, ideally - with an RS232 breakout box. Cheap DB9 to DB9 cables such as those - issued with UPSes often carry TXD/RXD/SG only, omitting handshake - lines such as DCD, RI, and DSR that are used to carry 1PPS. - Suspect this especially if the cable jacket looks too skinny to - hold more than three leads! - -3. Verify that your gpsd and kernel were both built with PPS support, - as previously described in the section on software prerequisites. - -4. Verify that the USB or RS232 device driver is accepting the ioctl - that tells it to wait on a PPS state change from the device. The - messages you hope *not* to see look like "KPPS cannot set PPS line - discipline" and "PPS ioctl(TIOCMIWAIT) failed". The former - can probably be corrected by running as root; the latter (which - should never happen with an RS232 device) probably means your USB - device driver lacks this wait capability entirely and cannot be - used for time service. - -5. If you have a solid 3D fix, a known-good cable, your software is - properly configured, the wait ioctl succeeded, but you still get no - PPS, then you might have a GPS receiver that fails to deliver PPS - off the chip to the RS232 or USB interface. You get to become - intimate with datasheets and pinouts, and might need to acquire a - different GPS receiver. - -== Running GPSD == - -If you're going to use gpsd for time service, you must run in -n mode -so the clock will be updated even when no clients are active. This option -is forced if you built GPSD with timeservice=yes as an option. - -Note that gpsd assumes that after each fix the GPS receiver will -assert 1PPS first and ship sentences reporting time of fix -second (and the sentence burst will end before the next 1PPS). Every -GPS we know of does things in this order. (However, on some very old -GPSes that defaulted to 4800 baud, long sentence bursts - notably -those containing a skyview - could slop over into the next second.) - -If you ever encounter an exception, it should manifest as reported -times that look like they're from the future and require a negative -fudge. If this ever happens, please report the device make and model -to the GPSD maintainers so we can flag it in our GPS hardware -database. - -There is another possible cause of small negative offsets which -shows up on the GR-601W: implementation bugs in your USB driver, -combining with quantization by the USB poll interval. This -doesn't mean the u-blox 6 inside it is actually emitting PPS -after the GPS timestamp is shipped. - -In order to present the smallest possible attack surface to -privilege-escalation attempts, gpsd, if run as root, drops its root -privileges very soon after startup - just after it has opened any -serial device paths passed on the command line. - -Thus, KPPS can only be used with devices passed that way, not with -GPSes that are later presented to gpsd by the hotplug system. Those -hotplug devices may, however, be able to use plain, non-kernel -PPS. gpsd tries to automatically fall back to this when absence of -root permissions makes KPPS unavailable. - -In general, if you start gpsd as other than root, the following things -will happen that degrade the accuracy of reported time: - -1. Devices passed on the command line will be unable to use KPPS and -will fall back to the same plain PPS that all hotplug devices must -use, increasing the associated error from ~1 uSec to about ~5 uSec. - -2. gpsd will be unable to renice itself to a higher priority. This -action helps protect it against jitter induced by variable system -load. It's particularly important if your NTP server is a general-use -computer that's also handling mail or web service or development. - -3. The way you have to configure ntpd and chrony will change away -from what we show you here; ntpd will need to be told different -shared-memory segment numbers, and chronyd will need a different -socket location. - -You may also find gpsd can't open serial devices at all if your -OS distribution has done "secure" things with the permissions. - -== Feeding NTPD from GPSD == - -Most Unix systems get their time service through ntpd, a very old and -stable open-source software suite which is the reference -implementation of NTP. The project home page is <>. We -recommend using NTPsec, a recent fork that is improved and -security-hardened <>. - -When gpsd receives a sentence with a timestamp, it packages the -received timestamp with current local time and sends it to a -shared-memory segment with an ID known to ntpd, the network time -synchronization daemon. If ntpd has been properly configured to -receive this message, it will be used to correct the system clock. - -When in doubt, the preferred method to start your timekeeping is: - ------------------------------------------------------------------------------ -$ su - (or sudo -s ) -# killall -9 gpsd ntpd -# gpsd -n /dev/ttyXX -# sleep 2 -# ntpd -gN -# sleep 2 -# cgps ------------------------------------------------------------------------------ - -where /dev/ttyXX is whatever 1PPS-capable device you have. In a -binary-package-based Linux distribution it is probable that ntpd -will already have been launched at boot time. - -It's best to have gpsd start first. That way when ntpd restarts it has -a good local time handy. If ntpd starts first, it will set the local -clock using a remote, probably pool, server. Then ntpd has to spend a -whole day slowly resynching the clock. - -If you're using dhcp3-client to configure your system, make sure -you disable /etc/dhcp3/dhclient-exit-hooks.d/ntp, as dhclient would -restart ntpd with an automatically created ntp.conf otherwise - and -gpsd would not be able to talk with ntpd any more. - -While gpsd may be runnable as non-root, you will get significantly -better accuracy of time reporting in root mode; the difference, while -almost certainly insignificant for feeding Stratum 1 time to clients -over the Internet, may matter for PTP service over a LAN. Typically -only root can access kernel PPS, whereas in non-root mode you're limited to -plain PPS (if that feature is available). As noted in the previous -section on 1PPS quality issues, this difference has performance -implications. - -The rest of these setup instructions will assume that you are starting -gpsd as root, with occasional glances at the non-root case. - -Now check to see if gpsd has correctly attached the shared-memory -segments in needs to communicate with ntpd. ntpd's rules for the -creation of these segments are: - -Segments 0 and 1:: - Permissions are 0600 - other programs can only read and - write this segment when running as root. - -Segments 2, 3 and above:: - Permissions are 0666 - other programs can read - and write as any user. If ntpd has been - configured to use these segments, any - unprivileged user is allowed to provide data - for synchronization. - -Because gpsd can be started either as root or non-root, it checks and -attaches the more privileged segment pair it can - either 0 and 1 or 2 -and 3. - -For each GPS receiver that gpsd controls, it will use the attached ntpshm -segments in pairs (for coarse clock and pps source, respectively) -starting from the first found segments. - -To debug, try looking at the live segments this way - ------------------------------------------------------------------------------ -# ipcs -m ------------------------------------------------------------------------------ - -If gpsd was started as root, the results should look like this: - ------------------------------------------------------------------------------ - ------ Shared Memory Segments -------- - key shmid owner perms bytes nattch status - 0x4e545030 0 root 700 96 2 - 0x4e545031 32769 root 700 96 2 - 0x4e545032 163842 root 666 96 1 - 0x4e545033 196611 root 666 96 1 ------------------------------------------------------------------------------ - -For a bit more data try this: - ------------------------------------------------------------------------------ -cat /proc/sysvipc/shm ------------------------------------------------------------------------------ - -If gpsd cannot open the segments, check that you are not running SELinux -or apparmor. Either may require you to configure a security exception. - -If you see the shared segments (keys 1314148400 -- 1314148403), and -no gpsd or ntpd is running then try removing them like this: - ------------------------------------------------------------------------------ -# ipcrm -M 0x4e545030 -# ipcrm -M 0x4e545031 -# ipcrm -M 0x4e545032 -# ipcrm -M 0x4e545033 ------------------------------------------------------------------------------ - -Here is a minimal sample ntp.conf configuration to work with GPSD run -as root, telling ntpd how to read the GPS notifications - ------------------------------------------------------------------------------ -pool us.pool.ntp.org iburst - -driftfile /var/lib/ntp/ntp.drift -logfile /var/log/ntp.log - -restrict default kod nomodify notrap nopeer noquery -restrict -6 default kod nomodify notrap nopeer noquery -restrict 127.0.0.1 mask 255.255.255.0 -restrict -6 ::1 - -# GPS Serial data reference (NTP0) -server 127.127.28.0 -fudge 127.127.28.0 time1 0.9999 refid GPS - -# GPS PPS reference (NTP1) -server 127.127.28.1 prefer -fudge 127.127.28.1 refid PPS ------------------------------------------------------------------------------ - -The number "0.9999" is a placeholder, to be explained shortly. It -is *not a number to be used in production* - it's too large. If you -can't replace it with a real value, it would be best to leave out the -clause entirely so the entry looks like - ------------------------------------------------------------------------------ -fudge 127.127.28.0 refid GPS ------------------------------------------------------------------------------ - -This is equivalent to declaring a time1 of 0. - -The pool statement adds a variable number of servers (often 10) as -additional time references needed by ntpd for redundancy and to give you -a reference to see how well your local GPS receiver is performing. If -you are outside of the USA replace the pool servers with one in your -local area. See <> for further information. - -The pool statement, and the driftfile and logfile declarations after it, -will not be strictly necessary if the default ntp.conf that your -distribution supplies gives you a working setup. The two pairs of -server and fudge declarations are the key. - -ntpd can be used in Denial of Service (DoS) attacks. To prevent that, -but still allow clients to request the local time, be sure the restrict -statements are in your ntpd config file. For more information see -<>. - -Users of ntpd versions older than revision ntp-4.2.5p138 should instead use -this ntp.conf, when gpsd is started as root: - ------------------------------------------------------------------------------ -pool us.pool.ntp.org iburst - -driftfile /var/lib/ntp/ntp.drift -logfile /var/log/ntp.log - -restrict default kod nomodify notrap nopeer noquery -restrict -6 default kod nomodify notrap nopeer noquery -restrict 127.0.0.1 mask 255.255.255.0 -restrict -6 ::1 - -# GPS Serial data reference (NTP0) -server 127.127.28.0 minpoll 4 maxpoll 4 -fudge 127.127.28.0 time1 0.9999 refid GPS - -# GPS PPS reference (NTP1) -server 127.127.28.1 minpoll 4 maxpoll 4 prefer -fudge 127.127.28.1 refid PPS ------------------------------------------------------------------------------ - -Users of ntpd versions prior to ntp-4.2.5 do not have the "pool" option. -Alternative configurations exist, but it is recommended that you upgrade -ntpd, if feasible. - -The magic pseudo-IP address 127.127.28.0 identifies unit 0 of the ntpd -shared-memory driver (NTP0); 127.127.28.1 identifies unit 1 (NTP1). -Unit 0 is used for in-band message timestamps and unit 1 for the (more -accurate, when available) time derived from combining in-band message -timestamps with the out-of-band PPS synchronization pulse. Splitting -these notifications allows ntpd to use its normal heuristics to weight -them. - -Different units - 2 (NTP2) and 3 (NTP3), respectively - must be used -when gpsd is not started as root. Some GPS HATs put PPS time on a GPIO -pin and will also use unit 2 (NTP2) for the PPS time correction. - -With this configuration, ntpd will read the timestamp posted by gpsd -every 64 seconds (16 if non-root) and send it to unit 0. - -The number after the parameter time1 (0.9999 in the example above) is a -"fudge", offset in seconds. It's an estimate of the latency between -the time source and the 'real' time. You can use it to compensate out -some of the fixed delays in the system. An 0.9999 fudge would be -ridiculously large. - -You may be able to find a value for the fudge by looking at the entry -for your GPS receiver type on <>. Later in this document -we'll explain methods for estimating a fudge factor on unknown -hardware. - -There is nothing magic about the refid fields; they are just labels -used for generating reports. You can name them anything you like. - -When you start gpsd, it will wait for a few good fixes before -attempting to process PPS. You should run gpsmon or cgps to verify -your GPS receiver has a 3D lock before worrying about timekeeping. - -After starting (as root) ntpd, then gpsd, a listing similar to the one -below should appear as the output of the command "ntpq -p" (after -allowing the GPS receiver to acquire a 3D fix). This may take up to -30 minutes if your GPS receiver has to cold-start or has a poor -skyview. - ------------------------------------------------------------------------------ - remote refid st t when poll reach delay offset jitter -============================================================================== -xtime-a.timefreq .ACTS. 1 u 40 64 377 59.228 -8.503 0.516 --bonehed.lcs.mit 18.26.4.106 2 u 44 64 377 84.259 4.194 0.503 -+clock.sjc.he.ne .CDMA. 1 u 41 64 377 23.634 -0.518 0.465 -+SHM(0) .GPS. 0 l 50 64 377 0.000 6.631 5.331 ------------------------------------------------------------------------------ - -The line with refid ".GPS." represents the in-band time reports from -your GPS receiver. When you are getting PPS then it may look like -this: - ------------------------------------------------------------------------------ - remote refid st t when poll reach delay offset jitter -============================================================================== -xtime-a.timefreq .ACTS. 1 u 40 64 377 59.228 -8.503 0.516 --bonehed.lcs.mit 18.26.4.106 2 u 44 64 377 84.259 4.194 0.503 -+clock.sjc.he.ne .CDMA. 1 u 41 64 377 23.634 -0.518 0.465 -+SHM(0) .GPS. 0 l 50 64 377 0.000 6.631 5.331 -*SHM(1) .PPS. 0 l 49 64 377 0.000 0.222 0.310 ------------------------------------------------------------------------------ - -Note the additional ".PPS." line. - -If the value under "reach" for the SHM lines remains zero, check that -gpsd is running; cgps reports a 3D fix; and the '-n' option was used. -Some GPS recievers specialized for time service can report time with signal -lock on only one satellite, but with most devices a 3D fix is -required. - -When the SHM(0) line does not appear at all, check your ntp.conf and -the system logs for error messages from ntpd. - -Notice the 1st and 3rd servers, stratum 1 servers, disagree by more than -8 mSec. The 1st and 2nd servers disagree by over 12 mSec. Our local -PPS reference agrees to the clock.sjc.he.net server within the expected -jitter of the GR-601W in use. - -When no other servers or local reference clocks appear in the NTP -configuration, the system clock will lock onto the GPS clock, but this -is a fragile setup - you can lose your only time reference if the GPS -receiver is temporarily unable to get satellite lock. - -You should always have at least two (preferably four) fallback servers -in your ntpd.conf for proper ntpd operation, in case your GPS receiver -fails to report time. The 'pool' command makes this happen. And -you'll need to adjust the offsets (fudges) in your ntp.conf so the -SHM(0) time is consistent with your other servers (and other local -reference clocks, if you have any). We'll describe how to diagnose and -tune your server configuration in a later section. - -Also note that after cold-starting ntpd it will calibrate for up to 15 -minutes before it starts adjusting the clock. Because the frequency -error estimate ("drift") that NTP uses isn't right when you first -start NTP, there will be a phase error that persists while the -frequency is estimated. So if your clock is a litle slow, then it -will keep getting behind, and the positive offset will cause NTP to -adjust the phase forward and also increase the frequency offset error. -After a day or so or maybe less the frequency estimate will be very -close and there won't be a persistent offset. - -The GPSD developers would like to receive information about the -offsets (fudges) observed by users for each type of receiver. If your -GPS receiver is not present in <>, or doesn't have a -recommended fudge, or you see a fudge value very different from what's -there, send us the output of the "ntpq -p" command and the make and -type of receiver. - -== Feeding chrony from GPSD == - -chrony is an alternative open-source implementation of NTP service, -originally designed for systems with low-bandwidth or intermittent -TCP/IP service. It interoperates with ntpd using the same NTP -protocols. Unlike ntpd which is designed to always be connected to -multiple internet time sources, chrony is designed for long periods -of offline use. Like ntpd, it can either operate purely as a client -or provide time service. The chrony project has a home page at -<>. Its documentation includes an instructive feature comparison -with ntpd at <>. - -gpsd, when run as root, feeds reference clock information to chronyd -using a socket named /var/run/chrony.ttyXX.sock (where ttyXX is -replaced by the GPS receiver's device name. This allows multiple GPS -receivers to feed one chronyd. - -No gpsd configuration is required to talk to chronyd. chronyd is -configured using the file /etc/chrony.conf or /etc/chrony/chrony.conf. -Check your distributions documentation for the correct location. To get -chronyd to connect to gpsd using the basic ntpd compatible SHM method -add this to use this basic chrony.conf file: - ------------------------------------------------------------------------------ -server 0.us.pool.ntp.org -server 1.us.pool.ntp.org -server 2.us.pool.ntp.org -server 3.us.pool.ntp.org - -driftfile /var/lib/chrony/drift - -allow - -# set larger delay to allow the NMEA source to overlap with -# the other sources and avoid the falseticker status -refclock SHM 0 refid GPS precision 1e-1 offset 0.9999 delay 0.2 -refclock SHM 1 refid PPS precision 1e-9 ------------------------------------------------------------------------------ - -You need to add the "precision 1e-9" on the SHM 1 line as chronyd fails -to read the precision from the SHM structure. Without knowing the high -precision of the PPS on SHM 1 it may not place enough importance on its -data. - -If you are outside of the USA replace the pool servers with one in your -local area. See <> for further information. - -The offset option is functionally like ntpd's time1 option, used to -correct known and constant latency. - -The allow option allows anyone on the internet to query your server's -time. - -To get chronyd to connect to gpsd using the more precise socket -method add this to your chrony.conf file (replacing ttyXX -with your device name). - -If running as root: - ------------------------------------------------------------------------------ -server 0.us.pool.ntp.org -server 1.us.pool.ntp.org -server 2.us.pool.ntp.org -server 3.us.pool.ntp.org - -driftfile /var/lib/chrony/drift - -allow - -# set larger delay to allow the NMEA source to overlap with -# the other sources and avoid the falseticker status -refclock SHM 0 refid GPS precision 1e-1 offset 0.9999 delay 0.2 -refclock SOCK /var/run/chrony.ttyXX.sock refid PPS ------------------------------------------------------------------------------ - -If not running as root change the "refclock SOCK" line to: - ------------------------------------------------------------------------------ -refclock SOCK /tmp/chrony.ttyXX.sock refid PPS ------------------------------------------------------------------------------ - -See the chrony man page for more detail on the configuration options -<>. - -Finally note that chronyd needs to be started before gpsd so the -socket is ready when gpsd starts up. - -If running as root, the preferred starting procedure is: - ------------------------------------------------------------------------------ -$ su - (or sudo -s ) -# killall -9 gpsd chronyd -# chronyd -f /etc/chrony/chrony.conf -# sleep 2 -# gpsd -n /dev/ttyXX -# sleep 2 -# cgps ------------------------------------------------------------------------------ - -After you have verified with cgps that your GPS receiver has a good 3D -lock you can check that gpsd is outputing good time by running ntpshmmon. - ------------------------------------------------------------------------------ -# ntpshmmon -ntpshmmon version 1 -# Name Seen@ Clock Real L Prec -sample NTP0 1461537438.593729271 1461537438.593633306 1461537438.703999996 0 -1 -sample NTP1 1461537439.000421494 1461537439.000007374 1461537439.000000000 0 -20 -sample NTP0 1461537439.093844900 1461537438.593633306 1461537438.703999996 0 -1 -sample NTP0 1461537439.621309382 1461537439.620958240 1461537439.703999996 0 -1 -sample NTP1 1461537440.000615395 1461537439.999994105 1461537440.000000000 0 -20 -sample NTP0 1461537440.122079148 1461537439.620958240 1461537439.703999996 0 -1 -^C ------------------------------------------------------------------------------ - -If you see only "NTP2", instead, you forgot to go root before starting gpsd. - -Once ntpshmmon shows good time data you can see how chrony is doing by -running 'chronyc sources'. Your output will look like this: - ------------------------------------------------------------------------------ -# chronyc sources - -210 Number of sources = 7 -MS Name/IP address Stratum Poll Reach LastRx Last sample -=============================================================================== -#- GPS 0 4 377 12 +3580us[+3580us] +/- 101ms -#* PPS 0 4 377 10 -86ns[ -157ns] +/- 181ns -^? vimo.dorui.net 3 6 377 23 -123ms[ -125ms] +/- 71ms -^? time.gac.edu 2 6 377 24 -127ms[ -128ms] +/- 55ms -^? 2001:470:1:24f::2:3 2 6 377 24 -122ms[ -124ms] +/- 44ms -^? 142.54.181.202 2 6 377 22 -126ms[ -128ms] +/- 73ms ------------------------------------------------------------------------------ - -The stratum is as in ntpq. The Poll is how many seconds elapse between samples. -The Reach is as in ntpq. LastRx is the time since the last successful -sample. Last sample is the offset and jitter of the source. - -To keep chronyd from preferring NMEA time over PPS time, you can add an -overlarge fudge to the NMEA time. Or add the suffix 'noselect' so it -is never used, just monitored. - -== Performance Tuning == - -This section is general and can be used with either ntpd or chronyd. -We'll have more to say about tuning techniques for the specific -implementations in later sections. - -The clock crystals used in consumer electronics have two properties we -are interested in: accuracy and stability. *Accuracy* is how well the -measured frequency matches the number printed on the can. *Stability* -is how well the frequency stays the same even if it isn't accurate. -(Long term aging is a third property that is interesting, but ntpd and -chrony both a use a drift history that is relatively short; thus, -this is not a significant cause of error.) - -Typical specs for oscillator packages are 20, 50, 100 ppm. That includes -everything; initial accuracy, temperature, supply voltage, aging, etc. - -With a bit of software, you can correct for the inaccuracy. ntpd and -chrony both call it *drift*. It just takes some extra low order bits -on the arithmetic doing the time calculations. In the simplest case, -if you thought you had a 100 MHz crystal, you need to change that to -something like 100.000324. The use of a PPS signal from gpsd -contributes directly to this measurement. - -Note that a low drift contributes to stability, not necessarily accuracy. - -The major source of instability is temperature. Ballpark is the drift -changes by 1 PPM per degree C. This means that the drift does not stay -constant, it may vary with a daily and yearly pattern. This is why the -value of drift the ntpd uses is calculated over a (relatively) short time. - -So how do we calculate the drift? The general idea is simple. -Measure the time offset every N seconds over a longer window of time -T, plot the graph, and fit a straight line. The slope of that line is -the drift. The units cancel out. Parts-per-million is a handy scale. - -How do you turn that handwaving description into code? One easy way -is to set N=2 and pick the right T, then run the answer through a -low pass filter. In that context, there are two competing sources of -error. If T is too small, the errors on each individual measurement -of the offset time will dominate. If T is too big, the actual drift -will change while you are measuring it. In the middle is a sweet -spot. (For an example, see <>.) - -Both ntpd and chrony use this technique; ntpd also uses a more -esoteric form of estimation called a "PLL/FLL hybrid loop". How T and N are -chosen is beyond the scope of this HOWTO and varies by implementation -and tuning parameters. - -If you turn on the right logging level ("statistics loopstats peerstats" -for ntpd, "log measurements tracking" for chronyd) , that will record -both offset, drift, and the polling interval. The ntpd stats are easy to -feed to gnuplot, see the example script in the GPSD contrib directory. -The most important value is the offset reported in the 3rd field in -loopstats and the last field in tracking.log. With gnuplot you can -compare them (after concatenating the rotated logs): - ------------------------------------------------------------------------------ -plot "tracking.log" using 7 with lines, "loopstats" using 3 with lines ------------------------------------------------------------------------------ - -While your NTP daemon (ntpd or chrony) is adjusting the polling -interval, it is assuming that the drift is not changing. It gets -confused if your drift changes abruptly, say because you started some -big chunk of work on a machine that's usually idle and that raises the -temperature. - -Your NTP daemon writes out the drift every hour or so. (Less often if -it hasn't changed much to reduce the workload on flash file systems.) -On startup, it reloads the old value. - -If you restart the daemon, it should start with a close old drift -value and quickly converge to the newer slightly different value. If -you reboot, expect it to converge to a new/different drift value and -that may take a while depending on how different the basic calibration -factors are. - -=== ARP is the sound of your server choking === - -By default ntpd and chronyd poll remote servers every 64 seconds. This -is an unfortuneate choice. Linux by default only keeps an ARP table -entry for 60 seconds, anytime thereafter it may be flushed. - -If the ARP table has flushed the entry for a remote peer or server then -when the NTP server sends a request to the remote server an entire ARP -cycle will be added to the NTP packet round trip time (RTT). This will -throw off the time measurements to servers on the local lan. - -On a RaspberryPi ARP has been shown to impact the remote offset by up to -600 uSec in some rare cases. - -The solution is the same for both ntpd and chronyd, add the "maxpoll 5" -command to any 'server" or "peer directive. This will cause the maximum -polling period to be 32 seconds, well under the 60 second ARP timeout. - -=== Watch your temperatures === - -The stability of the system clock is very temperature dependent. A one -degree change in room temperature can create 0.1 ppm of clock frequency -change. Once simple way to see the effect is to place your running -NTP server inside bubble wrap. The time will take a quick and noticeable -jump. - -If you leave your NTP server in the bubble wrap you will notice some -improved local and remote offsets. - -=== Powersaving is not your friend === - -Normally enabling power saving features is a good thing: it saves you power. -But when your CPU changes power saving modes (cstates for Intel CPUs) the -impact on PPS timing is noticeable. For some reason the NO_HZ kernel -mode has a similar bad effect on timekeeping. - -To improve your timekeeping, turn off both features on Intel CPUs by -adding this to your boot command line: - ------------------------------------------------------------------------------ -nohz=off intel_idle.max_cstate=0 ------------------------------------------------------------------------------ - -For ARM, be sure NO_HZ is off: - ------------------------------------------------------------------------------ -nohz=off ------------------------------------------------------------------------------ - -You will also need to select the 'performance' CPU governor to keep ypur -CPU set to the maximum speed for continuous usage. How you see and set -your governor will be distribution specific. The easiest way it to -recompile your kernel to only provide the performance governor. - -== NTP tuning and performance details == - -This section deals specifically with ntpd. It discusses algorithms -used by the ntpd suite to measure and correct the system time. It is not -directly applicable to chronyd, although some design considerations -may be similar. - -It is hard to optimize what you can't visualize. The easiest way to -visualize ntpd performance is with ntpviz from <>. Once you -are regularly graphing your server performance it is much easier to see -the results of changes. - -=== NTP performance tuning === - -For good time stability, you should always have at least four other -servers in your ntpd or chrony configuration besides your GPS receiver -- in case, for example, your GPS receiver is temporarily unable to achieve -satellite lock, or has an attack of temporary insanity. You can find -public NTP servers to add to your configuration at <>. - -To minimize latency variations, use the national and regional -pool domains for your country and/or nearby ones. Your ntp.conf -configuration line should probably look like this - ------------------------------------------------------------------------------ -pool us.pool.ntp.org iburst ------------------------------------------------------------------------------ - -where "us" may be replaced by one of the zone/country codes the Pool -project supports (list behind the "Global" link at <>). The -"pool" tag expands to four randomly chosen servers by default. "iburst" -implements a fast start algorithm that also weeds out bad servers. - -Note that a server can be a poor performer (what the NTP documentation -colorfully calls a "falseticker") for any of three reasons. It may be -shipping bad time, or the best routes between you and it have large -latency variations (jitter), or it may have a time-asymmetric route, -to you (that is, B-to-A time is on average very different from A-to-B -time). Asymmetric routing is the most common cause of serious -problems. - -The standard tool for tuning ntpd is "ntpq" ("NTP query program"). To -show a list of all servers declared in ntp.conf and their statistics, -invoke it with the "-p" option. On a sample system configured with 7 -servers from the NTP pool project and one PPS GPS receiver attached -via RS232, this is the output: - ------------------------------------------------------------------------- -$ ntpq -p - remote refid st t when poll reach delay offset jitter -======================================================================== --arthur.testserv 162.23.41.56 2 u 62 64 377 5.835 -1.129 8.921 --ntppublic.uzh.c 130.60.159.7 3 u 62 64 377 6.121 -4.102 6.336 --smtp.irtech.ch 162.23.41.56 2 u 35 64 377 15.521 -1.677 8.678 -+time2.ethz.ch .PPS. 1 u 27 64 377 5.938 -1.713 16.404 --callisto.mysnip 192.53.103.104 2 u 53 64 377 49.357 -0.274 5.125 --shore.naturalne 122.135.113.81 3 u 22 64 377 14.676 -0.528 2.601 --ntp.univ-angers 195.220.94.163 2 u 41 64 377 40.678 -1.847 13.391 -+SHM(0) .GPS. 0 l 4 64 377 0.000 34.682 7.952 -*SHM(1) .PPS. 0 l 3 64 377 0.000 -2.664 0.457 ------------------------------------------------------------------------- - -The interesting columns are "remote", "st", "reach" and "offset". - -"remote" is the name of the remote NTP server. The character in its -first column shows its current state: "-" or "x" for out-of-tolerance -servers, "+" for good servers ("truechimers"), and "*" for the one good -server currently used as the primary reference. The calculations used to -determine a server's state are outside the scope of this document; -details are available in NTPv4 RFC 5905. - -"st" shows the remote server's stratum. - -"reach" is the octal representation of the remote server's reachability. -A bit is set if the corresponding poll of the server was successful, -i.e. the server returned a reply. New poll results are shifted in from -the least significant bit; results older than 8 polls are discarded. In -the absence of network problems, this should show "377". - -"offset" shows the mean offset in the times reported between this local -host and the remote server in milliseconds. This is the value that can -be fudged with the "time1" parameter of the GPS server line in ntp.conf. -If the offset is positive, reduce the time1 value and vice versa. - -The asterisk in this example indicates that ntpd has correctly -preferred .PPS. over .GPS., as it should. If for some reason it -locks on to GPS time as a preferred source, you can add an overlarge -fudge to the NMEA time to discourage it. Or add the suffix 'noselect' -so GPS time is never used, just monitored. - -A more detailed description of the output is available at -<>. - -In order to determine the correct GPS offset, do one of the following: - -==== Peerstats-based procedure ==== - -[start=1] -. Add these lines to ntp.conf: - ------------------------------------------------------------------------------ -statsdir /var/log/ntpstats/ -statistics peerstats -filegen peerstats file peerstats type day enable ------------------------------------------------------------------------------ - -This enables logging of the peer server statistics. - -. Make sure the directory exists properly. For ntpd as root do: - ------------------------------------------------------------------------------ - # mkdir -p /var/log/ntpstats - # chown ntp:ntp /var/log/ntpstats ------------------------------------------------------------------------------ - -. Start ntpd and let it run for at least four hours. -Periodically check progress with "ntpq -p" and wait -until change has settled out. - -. Calculate the average GPS offset using this script (a copy is -included as contrib/ntpoffset in the GPSD distribution): - ------------------------------------------------------------------------------ -awk ' - /127\.127\.28\.0/ { sum += $5 * 1000; cnt++; } - END { print sum / cnt; } -' >. ntpviz generates lots of pretty graphs -and html pages. It even calculates the correct IMT offset, and other -performance metrics for you. - -===== Format of the loopstats and peerstats files ===== - -The following is incorporated from the ntpd website, see <> - -.loopstats - -Record clock discipline loop statistics. Each system clock update -appends one line to the loopstats file set: - -Example: 50935 75440.031 0.000006019 13.778 0.000351733 0.013380 6 - -|================================ -|Item |Units |Description -|50935 |MJD |date -|75440.031 |s |time past midnight (UTC) -|0.000006019 |s |clock offset -|13.778 |PPM |frequency offset -|0.000351733 |s |RMS jitter -|0.013380 |PPM |RMS frequency jitter (aka wander) -|6 |log2 s |clock discipline loop time constant -|================================= - - -.peerstats - -Record peer statistics. Each NTP packet or reference clock update -received appends one line to the peerstats file set: - -Example: 48773 10847.650 127.127.4.1 9714 -0.001605376 0.000000000 0.001424877 0.000958674 - -|================================ -|Item |Units |Description -|48773 |MJD |date -|10847.650 |s |time past midnight (UTC) -|127.127.4.1 |IP |source address -|9714 |hex |status word -|-0.001605376 |s |clock offset -|0.000000000 |s |roundtrip delay -|0.001424877 |s |dispersion -|0.000958674 |s |RMS jitter -|================================ - -===== Measurement of delay ===== - -There are three parts to measuring and correcting for the delay in -processing the 1PPS signal. - -1. Running ntpd without using the IMT (but using the 1PPS time) -2. Measuring the delay between the two messages -3. Applying the correction factor - -We assume that you have successfully integrated GPSD with ntpd already. -You should also have a decent set of NTP servers you are syncing to. - -[start=1] -. Running ntpd without IMT - -Locate the line in your ntp.conf that refers to the SHM0 segment and -append 'noselect' to it. As an example, the first two lines in the sample -above will become: - --------------------- -server 127.127.28.0 minpoll 4 maxpoll 4 noselect -fudge 127.127.28.0 time1 0.420 refid GPS --------------------- - -ntpd will now continue to monitor the IMT from GPSD, but not use it -for its clock selection algorithm. It will still write out statistics to -the peerstats file. Once ntpd is stable (a few hours or so), we can -process the peerstats file. - -. Measuring the delay between the two messages - -From the 'peerstats' file, extract the lines corresponding to -127.127.28.0 - ------------ -grep 127.127.28.0 peerstats > peerstats.shm ------------ - -You can now examine the offset and jitter of the IMT. <> -suggests the following gnuplot fragment (you will need to set output -options before plotting). - ----------------- - set term gif - set output "fudge.gif" ----------------- - -If your gnuplot has X11 support, and you do not wish to save the plot, -the above may not be required. Use: - ---------------- - set term x11 ---------------- - -Now plot the GPSD shared memory clock deviations from the system -clock. (You will get the GPSD shared memory clock fudge value -estimate from this data when NTP has converged to your -satisfaction.) - ------------------- - gnuplot> plot "peerstats.shm" using ($2):($5):($8) with yerrorbars - gnuplot> replot "peerstats.shm" using ($2):($5) with lines ------------------- - -. Applying the correction factor - -By examining the plot generated above, you should be able to estimate -the offset between the 1PPS time and the GPS time. - -If, for example, your estimate of the offset is -0.32s, your time1 fudge -value will be '0.32'. Note the change of sign. - -=== Pollling Interval === - -ntpd seems to better use a PPS refclock when the polling interval is -as small as possible. The ntpd default minpoll is 6, and can be set to -as low as 4. NTPsec versions 0.9.5 and above of ntpd allow you to -set minpoll and maxpoll as low as 0. Changing minpoll from 4 to 0 may -reduce your PPS jitter by over a factor of 4. - ------------------------------------------------------------------------------ -server 127.127.28.1 minpoll 0 maxpoll 0 prefer ------------------------------------------------------------------------------ - -== Chrony performance tuning - -The easiest way to determine the offset with chronyd is probably to -configure the source whose offset should be measured with the noselect -option and a long poll, let chronyd run for at least 4 hours and -observe the offset reported in the chronyc sourcestats output. If the -offset is unstable, wait longer. For example: - -SHM 0 configured as: -refclock SHM 0 poll 8 filter 1000 noselect - ------------------------------------------------------------------------------ -# chronyc sourcestats -210 Number of sources = 6 -Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev -============================================================================== -SHM0 21 9 85m 4.278 4.713 +495ms 8896us -SHM1 20 8 307 0.000 0.002 +0ns 202ns -mort.cihar.com 21 8 72m 0.148 0.798 +668us 490us -vps2.martinpoljak.net 6 4 17m -53.200 141.596 -24ms 15ms -ntp1.kajot.cz 25 16 91m -0.774 1.494 -11ms 1859us -ntp1.karneval.cz 17 10 89m 0.127 0.539 -4131us 574us ------------------------------------------------------------------------------ - -In this case (Garmin 18x) the offset specified in the config for the -SHM 0 source should be around 0.495. - -//FIXME: What more can we say about chronyd tuning? - -== Providing local NTP service using PTP == - -By now if you have a good serial PPS signal your local clock should -have jitter on the order of 1 uSec. You do not want the hassle of -placing a GPS receiver on each of your local computers. So you -install chrony or ntp on your other hosts and configure them to use -your NTP PPS server as their local server. - -With your best setup on a lightly loaded GigE network you find that your -NTP clients have jitter on the order of 150 uSec, or 150 times worse -than your master. Bummer, you want to do much better, so you look to -the Precision Time Protocol <> for help. PTP is also known as IEEE -1588. - -With PTP you can easily synchronize NTP hosts to 5 uSec with some -generic NIC hardware and newer Linux kernels. Some of the Ethernet -drivers have been modified to time stamp network packets when sending and -receiving. This is done with the new SO_TIMESTAMPING socket option. No -hardware support is required. - -A more recent addition is PTP Hardware Clock (PHC) support. This requires -hardware support in the NIC. - -Software timestamping is more mature, available on more NICs, and almost -as accurate as hardware timestamping. Try it first. This HOWTO will -build on those results. - -One final wrinkle before proceeding with PTP. Ethernet ports have -something called <> (IEEE 802.3az). Percentage wise EEE can save -50% of the Ethernet energy needs. Sadly this is 50% of an already small -energy usage. Only important in large data centers. EEE can be very -disruptive to timekeeping. Up to almost 1 Sec of errors in offset, -wander and jitter. To see if you have EEE enabled, and then turn it -off: - ------------------------------------------------------------------------------ -# ethtool --show-eee eth0 -EEE Settings for eth0: - EEE status: enabled - inactive - Tx LPI: 0 (us) - Supported EEE link modes: 100baseT/Full - 1000baseT/Full - Advertised EEE link modes: 100baseT/Full - 1000baseT/Full - Link partner advertised EEE link modes: Not reported -# ethtool --set-eee eth0 eee off -# ethtool --show-eee eth0 -EEE Settings for eth1: - EEE status: disabled - Tx LPI: disabled - Supported EEE link modes: 100baseT/Full - 1000baseT/Full - Advertised EEE link modes: Not reported - Link partner advertised EEE link modes: Not reported ------------------------------------------------------------------------------ - -=== PTP with software timestamping === - -To start you need to verify that your running Linux kernel configuration -includes these two lines, or the same with "y" replaced by "m" to enable -the drivers as modules: - ------------------------------------------------------------------------------ -CONFIG_NETWORK_PHY_TIMESTAMPING=y -PTP_1588_CLOCK=y ------------------------------------------------------------------------------ - -Then you need to verify that your Ethernet driver supports PTP -by running this command as root: - ------------------------------------------------------------------------------ -# ethtool -T eth0 | fgrep SOFTWARE - software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE) - software-receive (SOF_TIMESTAMPING_RX_SOFTWARE) - software-system-clock (SOF_TIMESTAMPING_SOFTWARE) ------------------------------------------------------------------------------ - -If the result includes those three lines then you have support for -software PTP timestamping. We will leave hardware timestamping -for later. - -Next you will need the <> package, just follow the simple -instructions on their web page to download, compile and install on your -NTP server and its slaves. Be sure to also follow their instructions on -how to configure your Linux kernel. - -In this setup we will just use the ptp4l program. This program measures -the delay and offset between a master and slaves and shares that information -with chronyd or ntpd using an SHM. Since gpsd also uses SHM be very careful -not to have the two SHM servers stepping on the same shmid. - -If you are using ntpd, then add the last three lines below to your -master ntp.conf file to configure the SHM. - ------------------------------------------------------------------------------ -# GPS Serial data reference (NTP0) -server 127.127.28.0 -fudge 127.127.28.0 time1 0.9999 refid GPS - -# GPS PPS reference (NTP1) -server 127.127.28.1 prefer -fudge 127.127.28.1 refid PPS - -# local PTP reference (NTP2) -server 127.127.28.2 -fudge 127.127.28.2 refid PTP ------------------------------------------------------------------------------ - -If you are using chronyd, then add the last one line below to your -master chronyd.conf file to configure the SHM. - ------------------------------------------------------------------------------ -refclock SHM 0 refid GPS precision 1e-1 offset 0.9999 delay 0.2 -refclock SHM 1 refid PPS precision 1e-9 -refclock SHM 2 refid PTP precision 1e-9 ------------------------------------------------------------------------------ - -To configure the master ptp4l, create a new file -/usr/local/etc/ptp4l.conf with these contents: - ------------------------------------------------------------------------------ -[global] -# only syslog every 1024 seconds -summary_interval 10 - -# send to to chronyd/ntpd using SHM 2 -clock_servo ntpshm -ntpshm_segment 2 - -# set our priority high since we have PPS -priority1 10 -priority2 10 - -[eth0] ------------------------------------------------------------------------------ - -Now as root on the master, start the ptp4l daemon: - ------------------------------------------------------------------------------ -# ethtool --set-eee eth0 eee off -# ptp4l -S -f /usr/local/etc/ptp4l.conf & ------------------------------------------------------------------------------ - -Configuration of the master server is now complete. Now to configure -the slaves. If the slaves also have PPS then configure them as masters. -Otherwise you will stomp on your SHMs. - -If you are using ntpd, then add the last three lines below to your -master ntp.conf file to configure your one and only SHM. - ------------------------------------------------------------------------------ -# local PTP reference (NTP0) -server 127.127.28.0 -fudge 127.127.28.0 refid PTP ------------------------------------------------------------------------------ - -If you are using chronyd, then add the one line below to your master -chronyd.conf file to configure your one and only SHM. - ------------------------------------------------------------------------------ -refclock SHM 0 refid PTP precision 1e-9 ------------------------------------------------------------------------------ - -To configure the slave ptp4l, create a new file -/usr/local/etc/ptp4l.conf with these contents: - ------------------------------------------------------------------------------ -[global] -# only syslog every 1024 seconds -summary_interval 10 - -# send to to chronyd/ntpd using SHM 0 -clock_servo ntpshm -ntpshm_segment 0 - -[eth0] ------------------------------------------------------------------------------ - -Now as root on the slave, as with the master, turn off EEE and start the -ptp4l daemon: - ------------------------------------------------------------------------------ -# ethtool --set-eee eth0 eee off -# ptp4l -S -f /usr/local/etc/ptp4l.conf & ------------------------------------------------------------------------------ - -Configuration of the slave server is now complete. Follow the earlier -procedures for checking the jitter on the SHM on the slaves. Give it -a few hours to settle and your hosts will now be synced to around 5 uSec. - -=== PTP with hardware timestamping === - -Some NICs requires two additional kernel options. Just in case, verify -that your running Linux kernel configuration includes these lines, or -the same with "y" replaced by "m" to enable the drivers as modules: - ------------------------------------------------------------------------------ -CONFIG_DP83640_PHY=y -CONFIG_PTP_1588_CLOCK_PCH=y ------------------------------------------------------------------------------ - -Then you need to verify that your Ethernet driver supports PTP -by running ethtool as root and verify at least the following lines are -present in the output: - ------------------------------------------------------------------------------ -# ethtool -T eth0 - hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE) - hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE) - all (HWTSTAMP_FILTER_ALL) ------------------------------------------------------------------------------ - -Your NIC may have more features, and your driver may support them for -better results. - -In the software timestamping above the ptp4l program took care of all steps to -determine the slave offset from the master and feeding that to a a SHM for -ntpd or chronyd to use.o - -In hardware timestamping mode ptp4l will continue to perform most of -the work. An additional program, phc2sys, will take over the duties of -reading the hardware timestamps from the NIC, computing the offset, and -feeding that to the SHM. - -phc2sys will use the SHM exactly as ptp4l did previously so no -change is required to your ntpd or chronyd configuration. - -To keep things simple, for now, we will not touch the already configured -and working software timestamping master server. We will proceed to -configure a slave. - -To configure the slave ptp4l, edit your /usr/local/etc/ptp4l.conf -to remove the ntpshm options: - ------------------------------------------------------------------------------ -[global] -# only syslog every 1024 seconds -summary_interval 10 - -clock_servo linreg - -[eth0] ------------------------------------------------------------------------------ - -Now as root on the slave, as with the master, turn off EEE and start the -ptp4l daemon: - ------------------------------------------------------------------------------ -# ethtool --set-eee eth0 eee off -# ptp4l -H -f /usr/local/etc/ptp4l.conf & -# sleep 3 -# phc2sys -a -r -E ntpshm -m -M 0 & ------------------------------------------------------------------------------ - - -Configuration of the slave server is now complete. Follow the earlier -procedures for checking the jitter on the SHM on the slaves. - -Sadly, theory and practice diverge here. I have never succeeded in -making hardware timestamping work. I have successfully trashed my -host system clock. Tread carefully. If you make progress please -pass on some clue. - -== Providing public NTP service == - -<> has good advice on things to be sure you have done - and -are ready to do - before becoming a public server. One detail it -doesn't mention is that you'll need to un-firewall UDP port 123. The -NTP protocol does not use TCP, so no need to unblock TCP port 123. - -If and when you are ready to go public, see <>. - -== Acknowledgments == -Beat Bolli wrote much of the section on NTP -performance tuning. Hal Murray wrote -much of the section on NTP working and performance details. -Sanjeev Gupta assisted with editing. -Shawn Kohlsmith tweaked the Bibliography. -Jaap Winius cleaned up some terminology. - -The loopstats-based tuning procedure for ntpd was drafted by Sanjeev -Gupta , based on discussions on the GPSD list -<> in Oct and Nov 2013. Code examples are based on work by -Andy Walls . A copy of the original -email can be found at <>. A thorough review was contributed -by Jaap Winius . - -== References == - -[bibliography] - -- [[[TIME-INTRO]]] link:time-service-intro.html[Introduction to Time Service] - -- [[[WIKI-NTP]]] http://en.wikipedia.org/wiki/Network_Time_Protocol[Network Time Protocol] - -- [[[NTP-FAQ]]] http://www.ntp.org/ntpfaq/[NTP FAQ] - -- [[[SIRF-WOBBLE]]] http://www.megapathdsl.net/~hmurray/ntp/GPSSiRF-off.gif[Peer Offset of SiRF units] - -- [[[RFC-2783]]] http://tools.ietf.org/html/rfc2783[RFC 2783] - -- [[[RFC-5905]]] http://tools.ietf.org/html/rfc5905[RFC 5905] - -- [[[MACX-1]]] https://www.etsy.com/listing/280336400/navisys-gr-601w-u-blox-6-macx-1-usb-gps[Navisys GR-601W u-blox-6 "Macx-1" USB GPS receiver] - -- [[[CHRONY-COMPARE]]] http://chrony.tuxfamily.org/manual.html#Comparison-with-ntpd[ntpd (comparison with chrony)] - -- [[[CHRONYDEFAULT]]] https://lists.fedoraproject.org/pipermail/devel/2010-May/135679.html - -- [[[HARDWARE]]] http://catb.org/gpsd/hardware.html[Compatible Hardware] - -- [[[UBLOX-TIMING]]] http://www.u-blox.com/images/downloads/Product_Docs/Timing_AppNote_%28GPS.G6-X-11007%29.pdf[GPS-based timing considerations with u-blox 6 receivers] - -- [[[RPI]]] http://www.satsignal.eu/ntp/Raspberry-Pi-NTP.html[The Raspberry Pi as a Stratum-1 NTP Server] - -- [[[NTP.ORG]]] http://www.ntp.org/[Home of the Network Time Protocol project] - -- [[[NTPSEC.ORG]]] http://www.ntpsec.org/[Wecome to NTPsec] - -- [[[USE-POOL]]] http://www.pool.ntp.org/en/use.html[How do I use pool.ntp.org?] - -- [[[CVE-2009-3563]]] http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2009-3563 - -- [[[CHRONY]]] http://chrony.tuxfamily.org/[Chrony Home] - -- [[[CHRONY-MAN]]] http://chrony.tuxfamily.org/manual.html - -- [[[ADEV-PLOT]]] http://www.leapsecond.com/pages/adev-avg/[Allan deviation and Averaging] - -- [[[ZONES]]] http://www.pool.ntp.org/zone - -- [[[NTPQ-OUTPUT]]] http://nlug.ml1.co.uk/2012/01/ntpq-p-output/831[ntpq output description] - -- [[[JOIN-POOL]]] http://www.pool.ntp.org/en/join.html[How do I join pool.ntp.org?] - -- [[[ANDY-POST]]] http://lists.gnu.org/archive/html/gpsd-dev/2013-10/msg00152.html[Clarifications needed for the time-service HOWTO] - -- [[[NTP-MONOPT]]] http://www.eecis.udel.edu/~mills/ntp/html/monopt.html[NTP Monitoring] - -- [[[GPSD-LIST]]]http://lists.gnu.org/archive/html/gpsd-dev[gpsd-dev Archives] - -- [[[PTP]]] http://www.nist.gov/el/isd/ieee/ieee1588.cfm/[PTP] - -- [[[LINUX-PTP]]] http://linuxptp.sourceforge.net/[Linux PTP] - -- [[[EEE]]] https://en.wikipedia.org/wiki/Energy-Efficient_Ethernet[Energy-Efficient Ethernet] - -- [[[LVC]]] http://www.rjsystems.nl/en/2100-ntpd-garmin-gps-18-lvc-gpsd.php - -== Changelog == - -1.1, Nov 2013:: - Initial release. - -1.2, Aug 2014:: - Note that NetBSD now has PPS support. - -1.3, Aug 2014:: - Add a note about the GR-601W. - -1.4, Dec 2014:: - Cleaned up Bibliography - -2.0, Feb 2015:: - More about troubleshooting PPS delivery. Folded in Sanjeev - Gupta's Calibration Howto describing the loopstats-based - procedure. Added preliminary information on PTP. - -2.1 Mar 2015:: - More on PTP. Added link to Jaap Winius's page on GPS-18 setup. - -2.2 Mar 2015:: - Detailed explanation of NTP has moved to a new page, - link:time-service-intro.html[Introduction to Time Service]. - -2.3 Mar 2015:: - Use the NTP accuracy estimate from RFC 5905. - -2.4 Mar 2015:: - Removed some typos, corrected formatting, and minor changes. - A bit more specificity about root vs. non-root. - -2.5 Apr 2016:: - Note the existence of the GR-701W. - -2.6 May 2016:: - New section on GPS time. Note the existence of the GR-801W. - Describe the special timeserver build of GPSD. Recommend NTPsec. - Add Macx-1 link. - Add sections on ARP and temperature problems - -2.7 June 2016 - Add section on avoiding power saving. - -2.8 July 2016 - Mention required version of gpsd - Fix Typos. - -2.9 August 2016 - Fix typos. - -2.10 September 2016 - Mention ntpviz - Recommend minpoll=maxpoll=0 for PPS refclocks - Recommend NTPsec. - -// end diff --git a/www/protocol-evolution.adoc b/www/protocol-evolution.adoc new file mode 100644 index 00000000..c697b030 --- /dev/null +++ b/www/protocol-evolution.adoc @@ -0,0 +1,599 @@ += GPSD-NG: A Case Study in Application Protocol Evolution = +:description: A case study in the evolution of the gpsd protocol +:keywords: GPSD, protocol, evolution +Eric S. Raymond +v1.5.2, January 2016 + +This document is mastered in asciidoc format. If you are reading it in HTML, +you can find the original at the GPSD project website. + + +== Introduction == + +GPSD is a service daemon that collects data from serial and USB GPS +sensors attached to a host machine and presents it in a +simple-to-parse form on TCP/IP port 2947. This is a less trivial task +than it sounds, because GPS sensor interfaces are both highly variable +and really badly designed (see http://esr.ibiblio.org/?p=801[Why GPSes +suck, and what to do about it] for a description of NMEA 0183 and +other horrors). + +In this paper, however, we will be ignoring all the dodgy stuff that +goes on at GPSD's back end to concentrate on what happens at the front +- the request-response protocol through which client programs get +access to the information that GPSD acquires from its devices and +internal computations. + +The GPSD request-response protocol is entering its third generation of +design, and I think the way it has evolved spotlights some interesting +design issues and long-term trends in the design of network protocols +in general. To anticipate, these trends are: (1) changing tradeoffs +of bandwidth economy versus extensibility and explicitness, (2) a +shift from lockstep conversational interfaces to event streams, (3) +changes in the "sweet spot" of protocol designs due to increasing use +of scripting languages, and (4) protocols built on metaprotocols. + +Carrying these trends forward may even give us a bit of a glimpse at +the future of application-protocol design. + +== The first version: a simple conversational protocol == + +The very first version of GPSD, back in the mid-1990s, handled +NMEA GPSes only and was designed with a dead-simple request-response +protocol. To get latitude and longitude out of it, you'd connect +to port 2947 and have a conversation that looked like this: + +------------------------------------------------------------------------- +-> P +<- GPSD,P=4002.1207 07531.2540 +------------------------------------------------------------------------- + +That is GPSD reporting, the only way it could in the earliest protocol +version, that I'm at latitude about 40 north and 75 west. + +If you are a mathematician or a physicist, you're probably noticing +some things missing in this report. Like a timestamp, and a circular +error estimate, and an altitude. In fact, it was possible to get some +these data using the old protocol. You could make a compound request +like this: + +------------------------------------------------------------------------- +-> PAD +<- GPSD,P=4002.1207 07531.2540,A=351.27,D=2009:07:11T11:16Z +------------------------------------------------------------------------- + +For some devices (not all) you could add E and get error estimates. +Other data such as course and rate of climb/sink might be available +via other single-letter commands. I say "might be" because in those +early days gpsd didn't attempt to compute error estimates or velocities +if the GPS didn't explicitly supply them. I fixed that, later, but +this essay is about protocol design so I'm going to ignore all the +issues associated with the implementation for the rest of the discussion. + +The version 1 protocol is squarely in the tradition of classic textual +Internet protocols, even though it doesn't look much like (say) SMTP +transactions - requests are simple to emit and responses are easy to +parse. It was clearly designed with the more specific goal of +minimizing traffic volume between the daemon and its clients. It +accomplishes that goal quite well. + +== The second version: from conversational to streaming == + +However, when I started work on it it in 2004 there was already +pressure from the existing userbase to change at least one of the +protocol's major assumptions - that is, that the client would poll +whenever it wanted data. It's usually more convenient to be able to +say to the daemon "Speak!" and have it stream TPV +(time/position/velocity) reports back at you at the sensor's sampling +rate (usually once per second). Especially when, as with GPSD, you +have a client library that can spin in a thread picking up the updates +and dropping them in a struct somewhere that you specify. + +This was the first major feature I implemented. I called it "watcher +mode", and it required me to add two commands to the protocol. There +were already so many single-shot commands defined that we were close +to running out of letters for new ones; I was able to grab "W" for the +command that enables or disables watcher mode, but was left with the +not-exactly-intuitive "O" for the streaming TPV report format. Here's +how it looks: + +------------------------------------------------------------------------- +-> W=1 +<- GPSD,W=1 +<- GPSD,O=MID2 1118327700.280 0.005 46.498339529 7.567392712 1342.392 36.000 32.321 10.3787 0.091 -0.085 ? 38.66 ? 3 +<- GPSD,O=MID2 1118327701.280 0.005 46.498339529 7.567392712 1342.392 48.000 32.321 10.3787 0.091 -0.085 ? 50.67 ? 3 +<- GPSD,O=MID2 1118327702.280 0.005 46.498345996 7.567394427 1341.710 36.000 32.321 10.3787 0.091 -0.085 ? 38.64 ? 3 +<- GPSD,O=MID2 1118327703.280 0.005 46.498346855 7.567381517 1341.619 48.000 32.321 10.3787 0.091 -0.085 ? 50.69 ? 3 +<- GPSD,Y=MID4 1118327704.280 8:23 6 84 0 0:28 7 160 0 0:8 66 189 45 1:29 13 273 0 0:10 51 304 0 0:4 15 199 34 1:2 34 241 41 1:27 71 76 42 1: +<- GPSD,O=MID2 1118327704.280 0.005 46.498346855 7.567381517 1341.619 48.000 32.321 10.3787 0.091 -0.085 ? ? ? 3 +-> W=0 +<- GPSD,W=0 +------------------------------------------------------------------------- + +The fields in the O report are tag (an indication of the device +sentence that produced this report), time, time error estimate, +longitude, latitude, altitude, horizontal error estimate, vertical +error estimate, course, speed, climb/sink, error estimates for +those last three fields, and mode (an indication of fix quality). If +you care about issues like reporting units, read the documentation. + +The 'Y' report is a satellite skyview, giving right-ascension, +declination, and signal quality for each of the visible satellites. +GPSes usually report this every five cycles (seconds). + +The 'W', 'O' and 'Y' sentences, together, effectively constituted +version 2 of the protocol - designed for streaming use. The other +single-shot commands, though still supported, rapidly became +obsolescent. + +Attentive readers may wonder why I designed a novel 'O' format rather +that writing the watcher-mode command so that it could specify a +compound report format (like PADE) every second. Part of the answer +is, again, that we were running out of letters to associate with new +data fields like the error estimates. I wanted to use up as little of +the remaining namespace as I could get away with. + +Another reason is, I think, that I was still half-consciously thinking +of bit bandwidth as a scarce resource to be conserved. I had a bias +against designs that would associate "extra" name tags with the +response fields ("A=351.27") even though the longest tagged response +GPSD could be expected to generate would still be shorter than a +single Ethernet packet (1509 bytes). + +== Pressure builds for a redesign == + +Along about 2006, despite my efforts to conserve the remaining +namespace, we ran out of letters completely. As the PADE example +shows, the protocol parser interprets command words letter +by letter, so trying to wedge longer commands in by simple +fiat wouldn't work. Recruiting non-letter characters as +command characters would have been ugly and only postponed +the problem a bit, not solved it. + +'H' is actually still left, but at the time I believed we couldn't +commit the last letter (whatever it was) because we'd need it as an +inline switch to a new protocol. I started feeling pressure to +actually design a new protocol. Besides running out of command +namespace in the old one, a couple of things were happening that +implied we'd need to define new commands. + +What had used up the last of the command namespace was multi-device +support. Originally, GPSD could only monitor one GPS at a time. I +re-engineered it so it could monitor multiple GPSes, with GPS streams +available as data channels to which a client could connect one at a +time. I was thinking about use cases like this one: spot two GPSes on +either end of an oil tanker, use the position delta as a check on +reported true course. + +(For those of you wondering, this wasn't the huge job it may sound +like. I had carefully structured GPSD as a relatively small (about +5.5 KLOC) networking and dispatcher top-level calling a 30 KLOC driver +and services library, all of which was designed from the get-go to use +re-entrant structures. Thus, only the top layer needed to change, and +at that only about 1 KLOC of it actually did. Building the test +framework to verify the multi-device code in action was a bigger job.) + +Note that the "one at a time" limitation was imposed by the +protocol design, notably the fact that the 'O' record didn't contain +the name of the device it was reporting from. Thus, GPSD could not +mix reports from different devices without effectively discarding +information about where they had come from. + +Though I had just barely managed to cram in multi-GPS support without +overrunning the available command space, we were starting to look at +monitoring multiple *kinds* of devices in one session - RTCM2 +correction sources and NTRIP were the first examples. (These are both +protocols that support +http://www.esri.com/news/arcuser/0103/differential1of2.html[differential +GPS correction].) My chief lieutenant was muttering about making GPSD +report raw pseudorange data from the sensors that allow you to get at +that. It was abundantly clear that broadening GPSD's scope was going +to require command-set extensions. + +Even though I love designing application protocols only a little bit +less than I love designing domain-specific minilanguages, I dragged my +feet on tackling the GPSD-NG redesign for three years. I had a strong +feeling that I didn't understand the problem space well enough, and +that jumping into the effort prematurely might lock in some mistakes +that I would come to gravely regret later on. + +== JSON and the AISonauts == + +What finally got me off the dime in early 2009 were two developments - the +push of AIS and the pull of JSON. + +AIS is the marine http://www.navcen.uscg.gov/enav/ais/[Automatic +Identification System]. All the open-source implementations of AIS +packet decoding I could find were sketchy, incomplete, and not at a +quality level I was comfortable with. It quickly became apparent that +this was due to a paucity of freely available public information about +the applicable standards. + +http://esr.ibiblio.org/?p=888[I fixed that problem] - but having done +so, I was faced with the problem of just how GPSD is supposed to +report AIS data packets to clients in a way that can't be confused +with GPS data. This brought the GPSD-NG design problem to the front +burner again. + +Fortunately, my AIS-related research also led me to discover +http://www.json.org/[JSON], aka JavaScript Object Notation. And JSON +is *really nifty*, one of those ideas that seem so simple and +powerful and obvious once you've seen it that you wonder why it wasn't +invented sooner. + +In brief, JSON is a lightweight and human-readable way to serialize +data structures equivalent to Python dictionaries, with attributes +that can be numbers, strings, booleans, nested dictionary objects, +or variable-extent lists of any of these things. + +== GPSD-NG is born == + +I had played with several different protocol design possibilities +between 2006 and 2009, but none of them really felt right. My +breakthrough moment in the GPSD-NG design came when I thought this: +"Suppose all command arguments to GPSD-NG commands, and their +responses, were self-describing JSON objects?" + +In particular, the equivalent of the 'O' report shown above looks like +this in GPSD-NG (with some whitespace added to avoid hard-to-read +linewraps): + +------------------------------------------------------------------------- +{"class":"TPV","tag":"MID50","device":"/dev/pts/1", + "time":"2005-06-09T14:35:11.79", + "ept":0.005,"lat":46.498333338,"lon":7.567392712,"alt":1341.667, + "eph":48.000,"epv":32.321,"track":60.9597,"speed":0.161,"climb":-0.074, + "eps":50.73,"mode":3} +------------------------------------------------------------------------- + +To really appreciate what you can do with object-valued attributes, +however, consider this JSON equivalent of a 'Y' record. The skyview +is a sublist of objects, one per satellite in view: + +------------------------------------------------------------------------- +{"class":"SKY","tag":"MID2","device":"/dev/pts/1", + "time":"2005-06-09T14:35:11.79", + "reported":8,"satellites":[ + {"PRN":23,"el":6,"az":84,"ss":0,"used":false}, + {"PRN":28,"el":7,"az":160,"ss":0,"used":false}, + {"PRN":8,"el":66,"az":189,"ss":40,"used":true}, + {"PRN":29,"el":13,"az":273,"ss":0,"used":false}, + {"PRN":10,"el":51,"az":304,"ss":36,"used":true}, + {"PRN":4,"el":15,"az":199,"ss":27,"used":false}, + {"PRN":2,"el":34,"az":241,"ss":36,"used":true}, + {"PRN":27,"el":71,"az":76,"ss":43,"used":true} + ]} +------------------------------------------------------------------------- + +(Yes, those "el" and "az" attributes are elevation and azimuth. "PRN" +is the satellite ID; "ss" is signal strength in decibels, and "used" +is a flag indicating whether the satellite was used in the current solution." + +These are rather more verbose than the 'O' or 'Y' records, but have several +compensating advantages: + +* Easily extensible. If we need to add more fields, we just add named + attributes. This is especially nice because... +* Fields with undefined values can be omitted. This means extension + fields don't weigh down the response format when we aren't using them. +* It's explicit. Much easier to read with eyeball than the corresponding + 'O' record. +* It includes the name of the device reporting the fix. This opens up + some design possibilities I will discuss in more detail in a bit. +* It includes, up front, a "class" tag that tells client software what it + is, which can be used to drive a parse. + +My first key decision was that these benefits are a good trade for the +increased verbosity. I had to wrestle with this a bit; I've been +programming a long time, and (as I mentioned previously) have reflexes +from elder days that push me to equate "good" with "requiring minimum +computing power and bandwidth". I reminded myself that it's 2009 and +machine resources are cheap; readability and extensibility are the goals +to play for. + +Once I had decided that, though, there remained another potential +blocker. The implementation language of gpsd and its principal client +library is C. There are lots of open-source JSON parsers in C out +there, but they all have the defect of requiring malloc(3) and handing +back a dynamic data structure that you then have to pointer-walk at +runtime. + +This is a problem, because one of my design rules for gpsd is no use +of malloc. Memory leaks in long-running service daemons are bad things; +using only static, fixed-extent data structures is a brutally effective +strategy for avoiding them. Note, this is only possible because the maximum +size of the packets gpsd sees is fairly small, and its algorithms are O(1) +in memory utilization. + +"Um, wait..." I hear you asking "...why accept that constraint when +gpsd hasn't had a requirement to parse JSON yet, just emit it as +responses?" Because I fully expected gpsd to have to parse structured +JSON arguments for commands. Here's an example, which I'll explain fully +later but right now just hint at the (approximate) GPSD-NG equivalent +of a 'W+R+' command. + +------------------------------------------------------------------------- +?WATCH={"raw":1,nmea:true} +------------------------------------------------------------------------- + +Even had I not anticipated parsing JSON arguments in gpsd, I try to +limit malloc use in the client libraries as well. Before the +new-protocol implementation the client library only used two calloc(3) +calls, in very careful ways. Now they use none at all. + +So my next challenge was to write and verify a tiny JSON parser that +is driven by sets of fixed-extent structures - they tell it what shape +of data to expect and at which static locations to drop the actual +parsed data; if the shape does not match what's expected, error out. +Fortunately, I am quite good at this sort of hacking - the +result, after a day and a half of work, fit in 310 LOC including +comments (but not including 165 LOC of unit-test code). + +== Un-channeling: the power == + +Both gpsd and its C client library could now count on parsing JSON; +that gave me my infrastructure. And an extremely strong one, too; +the type ontology of JSON is rich enough that I'm not likely to ever +have to replace it. Of course this just opened up the next question - +now that I can readily pass complex objects between gpsd and its +client libraries, what do I actually do with this capability? + +The possibility that immediately suggested itself was "get rid of channels". +In the old interface, subscribers could only listen to one device at +a time - again, this was a consequence of the fact that 'O' and 'Y' +reports were designed before multi-device support and didn't include a +device field. JSON reports can easily include a device field and +thus need not have this problem. + +Instead of a channel-oriented interface, then, how about one where the +client chooses what classes of message to listen to, and then gets +them from all devices? + +Note, however, that including the device field raises some problems of +its own. I do most of my gpsd testing with a utility I wrote called +gpsfake, which feeds one or more specified data logs through pty +devices so gpsd sees them as serial devices. Because X also uses pty +devices for virtual terminals, the device names that a gpsd instance +running under gpsfake sees may depend on random factors like the +number of terminal emulators I have open. This is a problem when +regression-testing! I thought this issue was going to require me +to write a configuration command that suppresses device display; I +ended up writing a sed filter in my regression-test driver instead. + +Now we come back to our previous example: + +------------------------------------------------------------------------- +?WATCH={"raw":true,nmea:true} +------------------------------------------------------------------------- + +This says: "Stream all reports from all devices at me, setting raw +mode and dumping as pseudo-NMEA if it's a binary protocol." The way to +add more controls to this is obvious, which is sort of the point -- +nothing like this could have fit in the fixed-length syntax of the old +pre-JSON protocol. + +This is not mere theory. At the time of writing, the ?WATCH command is +fully implemented in gpsd's Subversion repository, and I expect it to +ship ready for use in our next release (2.90). Total time to build +and test the JSON parsing infrastructure, the GPSD-NG parser, and the +gpsd internals enhancements needed to support multi-device listening? +About a working week. + +Just to round out this section, here is an example of what an +actual AIS transponder report looks like in JSON. + +------------------------------------------------------------------------- +{"class"="AIS","msgtype":5,"repeat":0,"mmsi":"351759000","imo":9134270, + "ais_version":0,"callsign":"3FOF8","shipname":"EVER DIADEM", + "shiptype":70,"to_bow":225,"to_stern":70,"to_port":1,"to_starboard":31, + "epfd":1,"eta":05-15T14:00Z,"draught":122,"destination":"NEW YORK", + "dte":0} +------------------------------------------------------------------------- + +The above is an AIS type 5 message identifying a ship - giving, among +other things, the ship's name and radio callsign and and destination +and ETA. You might get this from an AIS transceiver, if you had one +hooked up to your host machine; gpsd would recognize those data +packets coming in and automatically make AIS reports available as +an event stream. + +== The lessons of history == + +In the introduction, I called out three trends apparent over time in +protocol design. Let's now consider these in more detail. + +=== Bandwidth economy versus extensibility and explicitness === + +First, I noted *changing tradeoffs of bandwidth economy versus +extensibility and explicitness*. + +One way you can compare protocols is by the amount of overhead they +incur. In a binary format this is the percentage of the bit stream +that goes to magic numbers, framing bits, padding, checksums, and +the like. In a textual format the equivalent is the percentage +of the bitstream devoted to field delimiters, sentence start and +sentence-end sentinels, and (in protocols like NMEA 0183) textual +checksum fields. + +Another way you can compare protocols is by implicitness versus +explicitness. In the old GPSD protocol, you know the semantics of a +request parameter within a request implicitly, by where it is in +the order. In GPSD-NG, you know more explicitly because every parameter is a +name-attribute pair and you can inspect the name. + +Extensibility is the degree to which the protocol can have new +requests, responses, and parameters added without breaking old +implementations. + +In general, *both extensibility and overhead rise with the degree +of explicitness in the protocol*. The JSON-based TPV record has +has much higher overhead than the O record it replaces, but what +we gain from that is lots and *lots* of extensibility room. We +win three different ways: + +* The command/response namespace in inexhaustibly huge. +* Individual requests and responses can readily be extended by adding + new attributes without breaking old implementations. +* The type ontology of JSON is rich enough to make passing arbitrarily + complex data structures through it very easy. + +With respect to the tradeoffs between explicitness/extensibility and +overhead, we're at a very different place on the cost-benefit curves +today from when the original GPSD protocol was designed. + +Communications costs for the pipes that GPSD uses have +dropped by orders of magnitude in the decade-and-change since GPSD +was designed. Thus, squeezing every last bit of overhead out of the +protocol representation doesn't have the real economic payoff it used to. + +Under modern conditions, there is a strong case that implicit, +tightly-packed protocols are false economy. If (as with the first GPSD +protocol) they're so inextensible that natural growth in the +software breaks them, that's a clear down-check. It's better to design +for extensibility up front in order to avoid having to throw out +a lot of work later on. + +The direction this points in for the future is clear, especially +in combination with the increasing use of metaprotocols. + +=== From lockstep to streaming === + +Second, I noted *a shift from lockstep conversational interfaces to +event streams*. + +The big change in the second protocol version was watcher mode. One +of the possibilities this opens up is that you can put the report +interpreter into an asychronous thread that magically updates a C +struct for you every so often, without the rest of your program having +to know or care how that is being done (except possibly by waiting a +mutex to ensure it doesn't read a partially-updated state). + +Analogous developments have been visible in other Internet protocols +over roughly the same period. Compare, for example, POP3 to IMAP. The +former is a lockstep protocol, the latter designed for streaming - it's +why IMAP responses have a transaction ID tying them back to the +requesting command, so responses that are out of order due to +processing delays can be handled sanely. + +Systems software has generally been moving in a similar direction, +propelled there by distributed processing and networks with unavoidable +variable delays. There is a distant, but perceptible, relationship +between GPSD-NG's request-response objects and the way transactions +are handled within (for example) the X window system. + +This trend, too, seems certain to continue, as the Internet becomes +ever more like one giant distributed computing system. + +=== Type ontology recapitulates trends in language design === + +Third, *changes in the "sweet spot" of protocol designs +due to increasing use of scripting languages.* + +The most exciting thing about JSON to me, speaking as an application +protocol designer, is the rich type ontology - booleans, numbers, +strings, lists, and dictionaries - and the ability to nest them to any +level. In an important sense that is orthogonal to raw bandwidth, +this makes the pipe wider - it means complex, structured data can more +readily be passed through with a minimum of fragile and bug-prone +serialization/deserialization code. + +The fact that I could build a JSON parser to unpack to fixed-extent C +structures in 300-odd LOC demonstrates that this effect is a powerful +code simplifier even when the host language's type ontology is limited +to fixed-extent types and poorly matched to that of JSON (C lacks not +only variable-extent lists but also dictionaries). + +JSON is built on dictionaries; in fact, every JSON object is a legal +structure literal in the dictionary-centric Python language (with one +qualified exception near the JSON null value). It seems like a simple +idea in 2009, but the apparent simplicity relies on folk knowledge we +didn't have before Perl introduced dictionaries as a first-class data +type (c.1986) and Python built an object system around them (after +1991). + +Thus, GPSD-NG (and the JSON it's built on) reflects and recapitulates +long-term trends in language design, especially those associated with +the rise of scripting languages and of dictionaries as a first-class +type within them. + +This produces several mutually reinforcing feedback loops. The +rise of scripting languages makes it easier to use JSON to its full +potential, if only because deserialization is so trivial. JSON will +probably, in turn, promote the use of these languages. + +I think, in the future, application protocol designers will become +progressively less reluctant to rely on being able to pass around +complex data structures. JSON distils the standard type ontology of +modern scripting languages (Perl, Python, Ruby, and progeny) into a +common data language that is far more expressive than the structs of +yesteryear. + +== Protocols on top of metaprotocols == + +GPSD-NG is an application of JSON. Not a completely pure one; the +request identifiers, are, for convenience reasons, outside the JSON +objects. But close enough. + +In recent years, metaprotocols have become an important weapon in +the application-protocol designer's toolkit. XML, and its +progeny SOAP and XML-RPC, are the best known metaprotocols. YAML +(of which JSON is essentially a subset) has a following as well. + +Designing on top of a metaprotocol has several advantages. The most +obvious one is the presence of lots of open-source software to use for +parsing the metaprotocol. + +But it is probably more important in the long run that it saves one +from having to reinvent a lot of wheels and ad-hoc representations +at the design level. This effect is muted in XML, which has a weak +type ontology, but much more pronounced in YAML or JSON. As a +relevant example, I didn't have to think three seconds about the right +representation even for the relatively complex SKY object. + +== Paths not taken == + +Following the first public release of this paper, the major questions +to come up from early readers were "Why not XML?" and "Why not a +super-efficient packed binary protocol?" + +I would have thought the case against packed binary application +protocols was obvious from my preceding arguments, but I'll make it +explicit here: generally, they are even more rigid and inextensible +than a textual protocol relying on parameter ordering, and hence more +likely to break as your application evolves. They have significant +portability issues around things like byte order in numeric fields. +They are opaque; they cannot be audited or analyzed without bug-prone +special-purpose tools, adding a forbidding degree of complexity and +friction to the life-cycle maintenance costs. + +When the type ontology of your application includes only objects like +strings or numbers that (as opposed to large binary blobs like images) +have textual representations differing little in size from packed +binary, there is no case at all for incurring these large overheads. + +The case against XML is not as strong. An XML-based protocol at least +need not be rigidly inextensible and opaque. XML's problem is that, +while it's a good basis for document interchange, it doesn't naturally +express the sorts of data structures cooperating applications want to +pass around. + +While such things can be layered over XML with an appropriate schema, +the apparatus required for schema-aware parsing is necessarily +complicated and heavyweight - certainly orders of magnitude more so +than the little JSON parser I wrote. And XML itself is pretty +heavyweight, too - one's data tends to stagger under the bulk +of the markup parts. + +== Envoi == + +Finally, a note of thanks to the JSON developers... + +I think JSON does a better job of nailing the optimum in metaprotocols +than anything I've seen before - its combination of simplicity and +expressiveness certainly isn't matched by XML, for reasons already +called out in my discussion of paths not taken. + +I have found JSON pleasant to work with, liberating, and +thought-provoking; hence this paper. I will certainly reach for this +Swiss-army knife first thing, next time I have to design an +application protocol. diff --git a/www/protocol-evolution.txt b/www/protocol-evolution.txt deleted file mode 100644 index c697b030..00000000 --- a/www/protocol-evolution.txt +++ /dev/null @@ -1,599 +0,0 @@ -= GPSD-NG: A Case Study in Application Protocol Evolution = -:description: A case study in the evolution of the gpsd protocol -:keywords: GPSD, protocol, evolution -Eric S. Raymond -v1.5.2, January 2016 - -This document is mastered in asciidoc format. If you are reading it in HTML, -you can find the original at the GPSD project website. - - -== Introduction == - -GPSD is a service daemon that collects data from serial and USB GPS -sensors attached to a host machine and presents it in a -simple-to-parse form on TCP/IP port 2947. This is a less trivial task -than it sounds, because GPS sensor interfaces are both highly variable -and really badly designed (see http://esr.ibiblio.org/?p=801[Why GPSes -suck, and what to do about it] for a description of NMEA 0183 and -other horrors). - -In this paper, however, we will be ignoring all the dodgy stuff that -goes on at GPSD's back end to concentrate on what happens at the front -- the request-response protocol through which client programs get -access to the information that GPSD acquires from its devices and -internal computations. - -The GPSD request-response protocol is entering its third generation of -design, and I think the way it has evolved spotlights some interesting -design issues and long-term trends in the design of network protocols -in general. To anticipate, these trends are: (1) changing tradeoffs -of bandwidth economy versus extensibility and explicitness, (2) a -shift from lockstep conversational interfaces to event streams, (3) -changes in the "sweet spot" of protocol designs due to increasing use -of scripting languages, and (4) protocols built on metaprotocols. - -Carrying these trends forward may even give us a bit of a glimpse at -the future of application-protocol design. - -== The first version: a simple conversational protocol == - -The very first version of GPSD, back in the mid-1990s, handled -NMEA GPSes only and was designed with a dead-simple request-response -protocol. To get latitude and longitude out of it, you'd connect -to port 2947 and have a conversation that looked like this: - -------------------------------------------------------------------------- --> P -<- GPSD,P=4002.1207 07531.2540 -------------------------------------------------------------------------- - -That is GPSD reporting, the only way it could in the earliest protocol -version, that I'm at latitude about 40 north and 75 west. - -If you are a mathematician or a physicist, you're probably noticing -some things missing in this report. Like a timestamp, and a circular -error estimate, and an altitude. In fact, it was possible to get some -these data using the old protocol. You could make a compound request -like this: - -------------------------------------------------------------------------- --> PAD -<- GPSD,P=4002.1207 07531.2540,A=351.27,D=2009:07:11T11:16Z -------------------------------------------------------------------------- - -For some devices (not all) you could add E and get error estimates. -Other data such as course and rate of climb/sink might be available -via other single-letter commands. I say "might be" because in those -early days gpsd didn't attempt to compute error estimates or velocities -if the GPS didn't explicitly supply them. I fixed that, later, but -this essay is about protocol design so I'm going to ignore all the -issues associated with the implementation for the rest of the discussion. - -The version 1 protocol is squarely in the tradition of classic textual -Internet protocols, even though it doesn't look much like (say) SMTP -transactions - requests are simple to emit and responses are easy to -parse. It was clearly designed with the more specific goal of -minimizing traffic volume between the daemon and its clients. It -accomplishes that goal quite well. - -== The second version: from conversational to streaming == - -However, when I started work on it it in 2004 there was already -pressure from the existing userbase to change at least one of the -protocol's major assumptions - that is, that the client would poll -whenever it wanted data. It's usually more convenient to be able to -say to the daemon "Speak!" and have it stream TPV -(time/position/velocity) reports back at you at the sensor's sampling -rate (usually once per second). Especially when, as with GPSD, you -have a client library that can spin in a thread picking up the updates -and dropping them in a struct somewhere that you specify. - -This was the first major feature I implemented. I called it "watcher -mode", and it required me to add two commands to the protocol. There -were already so many single-shot commands defined that we were close -to running out of letters for new ones; I was able to grab "W" for the -command that enables or disables watcher mode, but was left with the -not-exactly-intuitive "O" for the streaming TPV report format. Here's -how it looks: - -------------------------------------------------------------------------- --> W=1 -<- GPSD,W=1 -<- GPSD,O=MID2 1118327700.280 0.005 46.498339529 7.567392712 1342.392 36.000 32.321 10.3787 0.091 -0.085 ? 38.66 ? 3 -<- GPSD,O=MID2 1118327701.280 0.005 46.498339529 7.567392712 1342.392 48.000 32.321 10.3787 0.091 -0.085 ? 50.67 ? 3 -<- GPSD,O=MID2 1118327702.280 0.005 46.498345996 7.567394427 1341.710 36.000 32.321 10.3787 0.091 -0.085 ? 38.64 ? 3 -<- GPSD,O=MID2 1118327703.280 0.005 46.498346855 7.567381517 1341.619 48.000 32.321 10.3787 0.091 -0.085 ? 50.69 ? 3 -<- GPSD,Y=MID4 1118327704.280 8:23 6 84 0 0:28 7 160 0 0:8 66 189 45 1:29 13 273 0 0:10 51 304 0 0:4 15 199 34 1:2 34 241 41 1:27 71 76 42 1: -<- GPSD,O=MID2 1118327704.280 0.005 46.498346855 7.567381517 1341.619 48.000 32.321 10.3787 0.091 -0.085 ? ? ? 3 --> W=0 -<- GPSD,W=0 -------------------------------------------------------------------------- - -The fields in the O report are tag (an indication of the device -sentence that produced this report), time, time error estimate, -longitude, latitude, altitude, horizontal error estimate, vertical -error estimate, course, speed, climb/sink, error estimates for -those last three fields, and mode (an indication of fix quality). If -you care about issues like reporting units, read the documentation. - -The 'Y' report is a satellite skyview, giving right-ascension, -declination, and signal quality for each of the visible satellites. -GPSes usually report this every five cycles (seconds). - -The 'W', 'O' and 'Y' sentences, together, effectively constituted -version 2 of the protocol - designed for streaming use. The other -single-shot commands, though still supported, rapidly became -obsolescent. - -Attentive readers may wonder why I designed a novel 'O' format rather -that writing the watcher-mode command so that it could specify a -compound report format (like PADE) every second. Part of the answer -is, again, that we were running out of letters to associate with new -data fields like the error estimates. I wanted to use up as little of -the remaining namespace as I could get away with. - -Another reason is, I think, that I was still half-consciously thinking -of bit bandwidth as a scarce resource to be conserved. I had a bias -against designs that would associate "extra" name tags with the -response fields ("A=351.27") even though the longest tagged response -GPSD could be expected to generate would still be shorter than a -single Ethernet packet (1509 bytes). - -== Pressure builds for a redesign == - -Along about 2006, despite my efforts to conserve the remaining -namespace, we ran out of letters completely. As the PADE example -shows, the protocol parser interprets command words letter -by letter, so trying to wedge longer commands in by simple -fiat wouldn't work. Recruiting non-letter characters as -command characters would have been ugly and only postponed -the problem a bit, not solved it. - -'H' is actually still left, but at the time I believed we couldn't -commit the last letter (whatever it was) because we'd need it as an -inline switch to a new protocol. I started feeling pressure to -actually design a new protocol. Besides running out of command -namespace in the old one, a couple of things were happening that -implied we'd need to define new commands. - -What had used up the last of the command namespace was multi-device -support. Originally, GPSD could only monitor one GPS at a time. I -re-engineered it so it could monitor multiple GPSes, with GPS streams -available as data channels to which a client could connect one at a -time. I was thinking about use cases like this one: spot two GPSes on -either end of an oil tanker, use the position delta as a check on -reported true course. - -(For those of you wondering, this wasn't the huge job it may sound -like. I had carefully structured GPSD as a relatively small (about -5.5 KLOC) networking and dispatcher top-level calling a 30 KLOC driver -and services library, all of which was designed from the get-go to use -re-entrant structures. Thus, only the top layer needed to change, and -at that only about 1 KLOC of it actually did. Building the test -framework to verify the multi-device code in action was a bigger job.) - -Note that the "one at a time" limitation was imposed by the -protocol design, notably the fact that the 'O' record didn't contain -the name of the device it was reporting from. Thus, GPSD could not -mix reports from different devices without effectively discarding -information about where they had come from. - -Though I had just barely managed to cram in multi-GPS support without -overrunning the available command space, we were starting to look at -monitoring multiple *kinds* of devices in one session - RTCM2 -correction sources and NTRIP were the first examples. (These are both -protocols that support -http://www.esri.com/news/arcuser/0103/differential1of2.html[differential -GPS correction].) My chief lieutenant was muttering about making GPSD -report raw pseudorange data from the sensors that allow you to get at -that. It was abundantly clear that broadening GPSD's scope was going -to require command-set extensions. - -Even though I love designing application protocols only a little bit -less than I love designing domain-specific minilanguages, I dragged my -feet on tackling the GPSD-NG redesign for three years. I had a strong -feeling that I didn't understand the problem space well enough, and -that jumping into the effort prematurely might lock in some mistakes -that I would come to gravely regret later on. - -== JSON and the AISonauts == - -What finally got me off the dime in early 2009 were two developments - the -push of AIS and the pull of JSON. - -AIS is the marine http://www.navcen.uscg.gov/enav/ais/[Automatic -Identification System]. All the open-source implementations of AIS -packet decoding I could find were sketchy, incomplete, and not at a -quality level I was comfortable with. It quickly became apparent that -this was due to a paucity of freely available public information about -the applicable standards. - -http://esr.ibiblio.org/?p=888[I fixed that problem] - but having done -so, I was faced with the problem of just how GPSD is supposed to -report AIS data packets to clients in a way that can't be confused -with GPS data. This brought the GPSD-NG design problem to the front -burner again. - -Fortunately, my AIS-related research also led me to discover -http://www.json.org/[JSON], aka JavaScript Object Notation. And JSON -is *really nifty*, one of those ideas that seem so simple and -powerful and obvious once you've seen it that you wonder why it wasn't -invented sooner. - -In brief, JSON is a lightweight and human-readable way to serialize -data structures equivalent to Python dictionaries, with attributes -that can be numbers, strings, booleans, nested dictionary objects, -or variable-extent lists of any of these things. - -== GPSD-NG is born == - -I had played with several different protocol design possibilities -between 2006 and 2009, but none of them really felt right. My -breakthrough moment in the GPSD-NG design came when I thought this: -"Suppose all command arguments to GPSD-NG commands, and their -responses, were self-describing JSON objects?" - -In particular, the equivalent of the 'O' report shown above looks like -this in GPSD-NG (with some whitespace added to avoid hard-to-read -linewraps): - -------------------------------------------------------------------------- -{"class":"TPV","tag":"MID50","device":"/dev/pts/1", - "time":"2005-06-09T14:35:11.79", - "ept":0.005,"lat":46.498333338,"lon":7.567392712,"alt":1341.667, - "eph":48.000,"epv":32.321,"track":60.9597,"speed":0.161,"climb":-0.074, - "eps":50.73,"mode":3} -------------------------------------------------------------------------- - -To really appreciate what you can do with object-valued attributes, -however, consider this JSON equivalent of a 'Y' record. The skyview -is a sublist of objects, one per satellite in view: - -------------------------------------------------------------------------- -{"class":"SKY","tag":"MID2","device":"/dev/pts/1", - "time":"2005-06-09T14:35:11.79", - "reported":8,"satellites":[ - {"PRN":23,"el":6,"az":84,"ss":0,"used":false}, - {"PRN":28,"el":7,"az":160,"ss":0,"used":false}, - {"PRN":8,"el":66,"az":189,"ss":40,"used":true}, - {"PRN":29,"el":13,"az":273,"ss":0,"used":false}, - {"PRN":10,"el":51,"az":304,"ss":36,"used":true}, - {"PRN":4,"el":15,"az":199,"ss":27,"used":false}, - {"PRN":2,"el":34,"az":241,"ss":36,"used":true}, - {"PRN":27,"el":71,"az":76,"ss":43,"used":true} - ]} -------------------------------------------------------------------------- - -(Yes, those "el" and "az" attributes are elevation and azimuth. "PRN" -is the satellite ID; "ss" is signal strength in decibels, and "used" -is a flag indicating whether the satellite was used in the current solution." - -These are rather more verbose than the 'O' or 'Y' records, but have several -compensating advantages: - -* Easily extensible. If we need to add more fields, we just add named - attributes. This is especially nice because... -* Fields with undefined values can be omitted. This means extension - fields don't weigh down the response format when we aren't using them. -* It's explicit. Much easier to read with eyeball than the corresponding - 'O' record. -* It includes the name of the device reporting the fix. This opens up - some design possibilities I will discuss in more detail in a bit. -* It includes, up front, a "class" tag that tells client software what it - is, which can be used to drive a parse. - -My first key decision was that these benefits are a good trade for the -increased verbosity. I had to wrestle with this a bit; I've been -programming a long time, and (as I mentioned previously) have reflexes -from elder days that push me to equate "good" with "requiring minimum -computing power and bandwidth". I reminded myself that it's 2009 and -machine resources are cheap; readability and extensibility are the goals -to play for. - -Once I had decided that, though, there remained another potential -blocker. The implementation language of gpsd and its principal client -library is C. There are lots of open-source JSON parsers in C out -there, but they all have the defect of requiring malloc(3) and handing -back a dynamic data structure that you then have to pointer-walk at -runtime. - -This is a problem, because one of my design rules for gpsd is no use -of malloc. Memory leaks in long-running service daemons are bad things; -using only static, fixed-extent data structures is a brutally effective -strategy for avoiding them. Note, this is only possible because the maximum -size of the packets gpsd sees is fairly small, and its algorithms are O(1) -in memory utilization. - -"Um, wait..." I hear you asking "...why accept that constraint when -gpsd hasn't had a requirement to parse JSON yet, just emit it as -responses?" Because I fully expected gpsd to have to parse structured -JSON arguments for commands. Here's an example, which I'll explain fully -later but right now just hint at the (approximate) GPSD-NG equivalent -of a 'W+R+' command. - -------------------------------------------------------------------------- -?WATCH={"raw":1,nmea:true} -------------------------------------------------------------------------- - -Even had I not anticipated parsing JSON arguments in gpsd, I try to -limit malloc use in the client libraries as well. Before the -new-protocol implementation the client library only used two calloc(3) -calls, in very careful ways. Now they use none at all. - -So my next challenge was to write and verify a tiny JSON parser that -is driven by sets of fixed-extent structures - they tell it what shape -of data to expect and at which static locations to drop the actual -parsed data; if the shape does not match what's expected, error out. -Fortunately, I am quite good at this sort of hacking - the -result, after a day and a half of work, fit in 310 LOC including -comments (but not including 165 LOC of unit-test code). - -== Un-channeling: the power == - -Both gpsd and its C client library could now count on parsing JSON; -that gave me my infrastructure. And an extremely strong one, too; -the type ontology of JSON is rich enough that I'm not likely to ever -have to replace it. Of course this just opened up the next question - -now that I can readily pass complex objects between gpsd and its -client libraries, what do I actually do with this capability? - -The possibility that immediately suggested itself was "get rid of channels". -In the old interface, subscribers could only listen to one device at -a time - again, this was a consequence of the fact that 'O' and 'Y' -reports were designed before multi-device support and didn't include a -device field. JSON reports can easily include a device field and -thus need not have this problem. - -Instead of a channel-oriented interface, then, how about one where the -client chooses what classes of message to listen to, and then gets -them from all devices? - -Note, however, that including the device field raises some problems of -its own. I do most of my gpsd testing with a utility I wrote called -gpsfake, which feeds one or more specified data logs through pty -devices so gpsd sees them as serial devices. Because X also uses pty -devices for virtual terminals, the device names that a gpsd instance -running under gpsfake sees may depend on random factors like the -number of terminal emulators I have open. This is a problem when -regression-testing! I thought this issue was going to require me -to write a configuration command that suppresses device display; I -ended up writing a sed filter in my regression-test driver instead. - -Now we come back to our previous example: - -------------------------------------------------------------------------- -?WATCH={"raw":true,nmea:true} -------------------------------------------------------------------------- - -This says: "Stream all reports from all devices at me, setting raw -mode and dumping as pseudo-NMEA if it's a binary protocol." The way to -add more controls to this is obvious, which is sort of the point -- -nothing like this could have fit in the fixed-length syntax of the old -pre-JSON protocol. - -This is not mere theory. At the time of writing, the ?WATCH command is -fully implemented in gpsd's Subversion repository, and I expect it to -ship ready for use in our next release (2.90). Total time to build -and test the JSON parsing infrastructure, the GPSD-NG parser, and the -gpsd internals enhancements needed to support multi-device listening? -About a working week. - -Just to round out this section, here is an example of what an -actual AIS transponder report looks like in JSON. - -------------------------------------------------------------------------- -{"class"="AIS","msgtype":5,"repeat":0,"mmsi":"351759000","imo":9134270, - "ais_version":0,"callsign":"3FOF8","shipname":"EVER DIADEM", - "shiptype":70,"to_bow":225,"to_stern":70,"to_port":1,"to_starboard":31, - "epfd":1,"eta":05-15T14:00Z,"draught":122,"destination":"NEW YORK", - "dte":0} -------------------------------------------------------------------------- - -The above is an AIS type 5 message identifying a ship - giving, among -other things, the ship's name and radio callsign and and destination -and ETA. You might get this from an AIS transceiver, if you had one -hooked up to your host machine; gpsd would recognize those data -packets coming in and automatically make AIS reports available as -an event stream. - -== The lessons of history == - -In the introduction, I called out three trends apparent over time in -protocol design. Let's now consider these in more detail. - -=== Bandwidth economy versus extensibility and explicitness === - -First, I noted *changing tradeoffs of bandwidth economy versus -extensibility and explicitness*. - -One way you can compare protocols is by the amount of overhead they -incur. In a binary format this is the percentage of the bit stream -that goes to magic numbers, framing bits, padding, checksums, and -the like. In a textual format the equivalent is the percentage -of the bitstream devoted to field delimiters, sentence start and -sentence-end sentinels, and (in protocols like NMEA 0183) textual -checksum fields. - -Another way you can compare protocols is by implicitness versus -explicitness. In the old GPSD protocol, you know the semantics of a -request parameter within a request implicitly, by where it is in -the order. In GPSD-NG, you know more explicitly because every parameter is a -name-attribute pair and you can inspect the name. - -Extensibility is the degree to which the protocol can have new -requests, responses, and parameters added without breaking old -implementations. - -In general, *both extensibility and overhead rise with the degree -of explicitness in the protocol*. The JSON-based TPV record has -has much higher overhead than the O record it replaces, but what -we gain from that is lots and *lots* of extensibility room. We -win three different ways: - -* The command/response namespace in inexhaustibly huge. -* Individual requests and responses can readily be extended by adding - new attributes without breaking old implementations. -* The type ontology of JSON is rich enough to make passing arbitrarily - complex data structures through it very easy. - -With respect to the tradeoffs between explicitness/extensibility and -overhead, we're at a very different place on the cost-benefit curves -today from when the original GPSD protocol was designed. - -Communications costs for the pipes that GPSD uses have -dropped by orders of magnitude in the decade-and-change since GPSD -was designed. Thus, squeezing every last bit of overhead out of the -protocol representation doesn't have the real economic payoff it used to. - -Under modern conditions, there is a strong case that implicit, -tightly-packed protocols are false economy. If (as with the first GPSD -protocol) they're so inextensible that natural growth in the -software breaks them, that's a clear down-check. It's better to design -for extensibility up front in order to avoid having to throw out -a lot of work later on. - -The direction this points in for the future is clear, especially -in combination with the increasing use of metaprotocols. - -=== From lockstep to streaming === - -Second, I noted *a shift from lockstep conversational interfaces to -event streams*. - -The big change in the second protocol version was watcher mode. One -of the possibilities this opens up is that you can put the report -interpreter into an asychronous thread that magically updates a C -struct for you every so often, without the rest of your program having -to know or care how that is being done (except possibly by waiting a -mutex to ensure it doesn't read a partially-updated state). - -Analogous developments have been visible in other Internet protocols -over roughly the same period. Compare, for example, POP3 to IMAP. The -former is a lockstep protocol, the latter designed for streaming - it's -why IMAP responses have a transaction ID tying them back to the -requesting command, so responses that are out of order due to -processing delays can be handled sanely. - -Systems software has generally been moving in a similar direction, -propelled there by distributed processing and networks with unavoidable -variable delays. There is a distant, but perceptible, relationship -between GPSD-NG's request-response objects and the way transactions -are handled within (for example) the X window system. - -This trend, too, seems certain to continue, as the Internet becomes -ever more like one giant distributed computing system. - -=== Type ontology recapitulates trends in language design === - -Third, *changes in the "sweet spot" of protocol designs -due to increasing use of scripting languages.* - -The most exciting thing about JSON to me, speaking as an application -protocol designer, is the rich type ontology - booleans, numbers, -strings, lists, and dictionaries - and the ability to nest them to any -level. In an important sense that is orthogonal to raw bandwidth, -this makes the pipe wider - it means complex, structured data can more -readily be passed through with a minimum of fragile and bug-prone -serialization/deserialization code. - -The fact that I could build a JSON parser to unpack to fixed-extent C -structures in 300-odd LOC demonstrates that this effect is a powerful -code simplifier even when the host language's type ontology is limited -to fixed-extent types and poorly matched to that of JSON (C lacks not -only variable-extent lists but also dictionaries). - -JSON is built on dictionaries; in fact, every JSON object is a legal -structure literal in the dictionary-centric Python language (with one -qualified exception near the JSON null value). It seems like a simple -idea in 2009, but the apparent simplicity relies on folk knowledge we -didn't have before Perl introduced dictionaries as a first-class data -type (c.1986) and Python built an object system around them (after -1991). - -Thus, GPSD-NG (and the JSON it's built on) reflects and recapitulates -long-term trends in language design, especially those associated with -the rise of scripting languages and of dictionaries as a first-class -type within them. - -This produces several mutually reinforcing feedback loops. The -rise of scripting languages makes it easier to use JSON to its full -potential, if only because deserialization is so trivial. JSON will -probably, in turn, promote the use of these languages. - -I think, in the future, application protocol designers will become -progressively less reluctant to rely on being able to pass around -complex data structures. JSON distils the standard type ontology of -modern scripting languages (Perl, Python, Ruby, and progeny) into a -common data language that is far more expressive than the structs of -yesteryear. - -== Protocols on top of metaprotocols == - -GPSD-NG is an application of JSON. Not a completely pure one; the -request identifiers, are, for convenience reasons, outside the JSON -objects. But close enough. - -In recent years, metaprotocols have become an important weapon in -the application-protocol designer's toolkit. XML, and its -progeny SOAP and XML-RPC, are the best known metaprotocols. YAML -(of which JSON is essentially a subset) has a following as well. - -Designing on top of a metaprotocol has several advantages. The most -obvious one is the presence of lots of open-source software to use for -parsing the metaprotocol. - -But it is probably more important in the long run that it saves one -from having to reinvent a lot of wheels and ad-hoc representations -at the design level. This effect is muted in XML, which has a weak -type ontology, but much more pronounced in YAML or JSON. As a -relevant example, I didn't have to think three seconds about the right -representation even for the relatively complex SKY object. - -== Paths not taken == - -Following the first public release of this paper, the major questions -to come up from early readers were "Why not XML?" and "Why not a -super-efficient packed binary protocol?" - -I would have thought the case against packed binary application -protocols was obvious from my preceding arguments, but I'll make it -explicit here: generally, they are even more rigid and inextensible -than a textual protocol relying on parameter ordering, and hence more -likely to break as your application evolves. They have significant -portability issues around things like byte order in numeric fields. -They are opaque; they cannot be audited or analyzed without bug-prone -special-purpose tools, adding a forbidding degree of complexity and -friction to the life-cycle maintenance costs. - -When the type ontology of your application includes only objects like -strings or numbers that (as opposed to large binary blobs like images) -have textual representations differing little in size from packed -binary, there is no case at all for incurring these large overheads. - -The case against XML is not as strong. An XML-based protocol at least -need not be rigidly inextensible and opaque. XML's problem is that, -while it's a good basis for document interchange, it doesn't naturally -express the sorts of data structures cooperating applications want to -pass around. - -While such things can be layered over XML with an appropriate schema, -the apparatus required for schema-aware parsing is necessarily -complicated and heavyweight - certainly orders of magnitude more so -than the little JSON parser I wrote. And XML itself is pretty -heavyweight, too - one's data tends to stagger under the bulk -of the markup parts. - -== Envoi == - -Finally, a note of thanks to the JSON developers... - -I think JSON does a better job of nailing the optimum in metaprotocols -than anything I've seen before - its combination of simplicity and -expressiveness certainly isn't matched by XML, for reasons already -called out in my discussion of paths not taken. - -I have found JSON pleasant to work with, liberating, and -thought-provoking; hence this paper. I will certainly reach for this -Swiss-army knife first thing, next time I have to design an -application protocol. diff --git a/www/protocol-transition.adoc b/www/protocol-transition.adoc new file mode 100644 index 00000000..594d4c87 --- /dev/null +++ b/www/protocol-transition.adoc @@ -0,0 +1,450 @@ += Moving to GPSD-NG: a Guide for Client Developers = +:description: A Guide for Client Developers moving to GPSD-ND +:keywords: time, GPSD, gpsd, guide, developers, client +Eric S. Raymond +v1.10, Febuary 2011 + +This document is mastered in asciidoc format. If you are reading it in HTML, +you can find the original at the GPSD project website. + +== Why a new protocol? == + +GPSD has moved to a new request/response protocol. This move has been +forced upon us because the old one ran out of namespace. It was +designed with case-insensitive single-character command/response +codes. 25 of 26 ASCII alphabetics were already in use by 2006, and +there have been functional challenges accumulating over the last three +years that will require several more request/response codes - things +like reporting AIS data, reporting raw pseudoranges, and reporting +RTCM3. + +Yes, we could as a desperate expedient have pressed non-alphabetic +printables into service - but the result would have looked like +line noise and only delayed the day of reckoning. Instead, we've +written a new protocol that is upward-compatible with the old one +in that you can mix old and new syntax. + +There were other problems as well. The old command set encouraged +sloppy handling of data by supporting commands that return PVT and +fix-quality information in atomized partial form, without timestamps. + +There was also no way to support returning more than single-line +responses to a client. This was a problem for returning things like +[RINEX] format, which we'd like to be able to do when a device can +report pseudoranges. + +== The transition plan == + +We need to shed the code complexity and overhead of maintaining both +protocols at once. This will happen sooner than it otherwise might +have because gpsd is in part targeted for SBCs and other constrained +environments where shaving a few K off the runtime image can actually +matter. When it comes to keeping the codebase lean and mean, we try +harder. + +The old-protocol support was removed from the daemon in 2.91. Old +protocol will be supported in the client-side library for somewhat +longer, giving your applications a bridge period when they can speak +both old and new protocol -- but the client-side support for old +protocol will be removed when 3.0 ships. + +The 2.92 version, with the new protocol deployed, is be in Lucid +Lynx, the Ubuntu LTS release of April 2010. + +If you follow our transition advice now, you will be able to talk to +all old-protocol and new-protocol versions of the daemon until the 3.0 +shared client library is deployed, at which point your runtime will +silently get smaller but you may no longer be able to use 2.x daemon +versions any more. + +We're counting on binary-package dependencies to make the transition +easier. When you ship a release using the new interface library, +specify the GPSD package at version >= 2.90 to get the new shared +library; then, when the 3.0 interface library is deployed next year, +you shouldn't have to do anything. + +We'll try to make the transition easy, but we cannot guarantee no +problems. The sooner you start adapting your code, the less pain you +are likely to experience. The rest of this document will explain both +theory and practice, and give you specific pointers on how to fix +client code. + +== Virtue is rewarded == + +Since 2004, the way you were *supposed* to be using gpsd was through +one of the client libraries (in C or Python). If you have been doing +it right, you have been telling gpsd to stream data at you with the +'w' command, via application code probably looked something like this: + +------------------------------------------------------------------- + + gpsdata = gps_open(source.server, source.port); + + (void)gps_query(gpsdata, "w+x\n"); + + // This is in your application's main event loop somewhere. + // It polls gpsd for new data. + ... gps_poll(gpsdata) ... + + gps_close() + +------------------------------------------------------------------- + +If you have been virtuous, you need only to make four small changes to +your code. + +. Give gps_open() a third argument that is the address of a struct gps_data_t. +(This interface changed to avoid malloc(3) and make it possible to write +re-entrant client code.) + +. Replace the gps_query() call with: + +------------------------------------------------------------------- +gps_stream(gpsdata, WATCH_ENABLE, NULL) +------------------------------------------------------------------- + +This will tell whatever version of the client library your application +dynamically links to emit what it should under the hood, either old +or new protocol. Unless a target system carries a version of the +libgps shared library different from the gpsd version, everything +should work and continue to work through future updates. + +. Change gps_poll calls to gps_read calls. + +. If you have references to the 'satellites' member of the structure, +those need to change them to 'satellites_visible'. + +There. You're probably done, unless you relied on some parts of +struct gpsdata_t that application developers usually don't or issued +unusual configuration commands. Here are the exceptions: + +* You issued other gps_query() or gps_send() commands, such as "J=1". + If so, you'll need to learn how to say them in the new API (the J + command itself is dead, and you can just remove it entirely). That + is not difficult, and this document will cover what you need to + know. + +* Your application code referenced struct gpsdata_t members that no + longer exist. This will be obvious because your compilation will + fail. Later in this document you will learn how to fix these + problems. + +* You set a per-packet raw hook. This feature is gone; code + can now just look at the response buffer directly. + +* You set a thread hook. We have deleted the thread-hook portion of + the API; for discussion, see "Why threads are gone" below. + +You can probably ignore the rest of this document, unless +either (a) you want to learn about gpsd's new capabilities so you +can use them in creative ways, or (b) you want to caper with unholy glee +as you contemplate the trials awaiting the non-virtuous. + +If you are non-virtuous -- that is, you rolled your own client-side +interface -- you've had years of warning that this choice would +fail to insulate you from protocol details and cost you pain in the +future. That future is now. + +In the remainder of this document we will try to help you minimize the +pain. The main strategy for doing so is to *use libgps* (or its +functional equivalents in languages other than C). Scrap your +hand-rolled interface code! When you use libgps, compatibility issues +become *our* problem to solve rather than *yours*. + +== Binary stability == + +In the past, the GPSD project has not been very good about preserving +stability of the binary structure layout for struct gpsdata_t between +releases. There was a reason for this -- we were very focused +on reducing memory footprint for SBCs and embedded devices, so we +conditioned out various pieces of the strucure depending on what +features were or were not compiled in. + +We're not going to do this any more. It has been pointed out to us +that the friction costs of breaking shared-library compatibility are +higher than we were reckoning. The new layout has no sections +conditionalized; instead, we have moved a number of fields into +a union. From 2.90 on, the structure layout will change rarely, +only at major version bumps. + +== When the bough breaks == + +Even virtuous clients have to worry about version skew. Supposing you +have used libgps and not done anything exotic, you will still have +problems if the client library you linked and the instance of gpsd it +speaks to are using different protocols. + +The possible failure modes are pretty obvious. Transitions are +difficult. We're essentially relying on the distribution integrators +to ship libgps and gpsd updates at the same time, with sane +package dependencies. If that goes smoothly, applications may +not even notice the changes. We can hope... + +== Why threads are gone == + +We have deleted the two functions in the API that managed a +library-internal thread hook. Here's why: + +1. Actual use of it has been at best very rare and possibly nonexistent. + +2. Applications that want location handing to run in a thread are in + a better position to manage thread locks and mutexes themselves + than our client library can possibly be -- after all, the + application knows what all the other threads and mutex locks + are, and our library doesn't. + +3. We don't like to ship code we can't test, we didn't have a + regression test for the thread stuff, and writing one would + have been a painful expenditure of time better spent elsewhere. + +== On not doing things by halves == + +At the same time that pressure has been building to redesign the +protocol, we've been gaining experience in gpsd's application domain +that has made us rethink some of the assumptions behind the old one. + +Since we knew we were going to have a forced compatibility break at the +wire-protocol level anyway, we decided not to do things by halves. One +big break -- in the application model, struct gpsdata_t, and the +wire protocol behind it -- is better than three or four spread out +over a period of time. + +As a result, the new protocol is not an exact superset of the old one. +It reflects a different way of carving up the behavior space in gpsd's +application domain. And the shape of struct gpsdata_t, the +client-side interface structure, has changed in corresponding ways. + +Accordingly, there are three things a client developer will need to +understand about the new protocol. The first is theory: how its model +of the gpsd application domain is different. The second is practice: +how to issue new-style commands and interpret responses. The third, if +you have relied on the structure in a way that now breaks your +compile, is how that structure has changed. + +== How the theory has changed == + +=== Channels are gone === + +In old protocol, when you requested data from the daemon, it would +search for a device supplying the kind of data you had told it you +wanted (GPS, by default) and connect your listening channel to *that +single device*. The association between channel and device was set +when channel was first bound to device and implicit; reports weren't +labeled with the device name. You could request a specific device if +you wanted to. + +In the new protocol, channels are gone. You tell gpsd to stream +reports at you; thereafter, every time an attached GPS or other device +generates a report, you'll get it. There may be multiple devices +reporting; each report will come labeled with the name of the +originating device, and that name will be left in your client +structure along with the rest of the new data. + +In both protocols, when you poll gpsd and get data the client library +takes care of interpreting what comes up the wire from the daemon, and +merges the resulting data into your client structure (struct +gpsdata_t). + +The difference is that before, the API locked you to one device during +the life of the session. Now it potentially has to deal with a *set* +of devices, treated symmetrically. + +There are multiple reasons this change is a good idea. One is that it +makes coping with devices being hotplugged in or out completely +trivial from the client's point of view - it can just choose to ignore +the fact that the device IDs in the reports have changed. Also, the +channel-management hair in the interface goes away. Also, it means +that clients can treat identically the cases where (a) you have one +device reporting different kinds of data (e.g. a marine navigation +system reporting both GPS and AIS) and (b) you have several devices +reporting different kinds of data. + +=== From lockstep to streaming === + +A subtler change has to do with the difference between a lockstep +or conversational interface and a streaming, stateless one. + +In the earliest versions of GPSD, clients requested various pieces of +data by command. After each request, they would need to wait until a +response came back. Then, watcher mode was added. By saying "w+", +you could ask gpsd to stream GPS reports at you whenever it got them. + +In the new protocol, streaming is all there is. Every report coming +up from the daemon is tagged with its device and type. Instead of +issuing commands and then waiting for specific responses, clients +should expect any kind of report at any time and merge it into +client-local storage (libgps does this for you). + +This change is necessary to cope with devices that may send (for +example) mixed GPS and AIS data. In the future, the stream from +gpsd could include other kinds of data, such as the take from +a digital compass, water-temperature sensors, or even aircraft +transponders. + +=== Asynchronous-write handling === + +The old client code had an assumption baked into it that gps_poll() +can do one read call end expect the daemon to hand it an entire +\n-terminated packet. 99.9% of the time this is true, but socket +layers can do some remarkably perverse things. + +In 2.91 and later, what was gps_poll() and is now gps_read() behaves +in a subtly different way. Each call does exactly one read() call as +before, but the incoming data is now buffered; the logic to interpret +the buffer and empty it is called only when the read() contains a \n. +When that happens, the validity flags include the PACKET_SET mask. + +== How the command set has changed == + +If your code issues old-protocol commands 'A', 'D', 'E', 'M', 'P', +'T', 'U', or 'V', it is a wretched hive of scum and villainy that +probably hasn't changed since before the introduction of 'W' in +2004-2005. You are using the oldest single-shot commands and will +have to rewrite your interface significantly, as the new protocol does +not support equivalents. Use libgps. + +If your code issues B, C, or N commands, they need to change to +?DEVICE commands. See the protocol reference for details. + +The 'F' command has no equivalent in 2.90; consider teaching your +client to ignore fix updates when they don't have a specified "device" +or "class" tag, respectively. In 2.91 and later versions, use the "device" +option of the ?WATCH command for similar effect. + +The old 'G' command does not have an equivalent. It would be possible +to implement one, but we probably won't do it unless there is actual +demand (and we don't expect any). + +The old 'I' command has no equivalent. You probably issued it as part +of an initialization string, hoping that a subtype string would later +show up in gps_id so you could post it somewhere. In the new +protocol, when a device sends back subtype information the daemon +ships the client an object of class DEVICE with a device tag and +subtype fields. Watch for that and process appropriately. + +The old 'J' command is dead. gpsd now detects the end of the reporting +cycle reliably and ships on that, buffering data during the individual +reporting cycle. + +The old 'K' command is replaced by ?DEVICES. + +The old 'L' command is replaced by ?VERSION. Note that the daemon now +ships a version response to each client on connect, so it will +probably never be necessary for you to issue a ?VERSION request. + +The old 'M' command has no equivalent. Mode is reported in the TPV response. + +The old 'O' and 'Y' commands are gone. Use ?WATCH and sample the +stream instead. + +The old 'Q' command has no equivalent. DOPs are reported in the SKY response. + +The 'S' command has no equivalent, because it is not well defined what +value should be presented for binary protocols. + +The old 'R' command has been replaced by three optional attributes in +?WATCH. Include the WATCH_RARE, WATCH_RAW and/or WATCH_NMEA masks in +the argument of gps_stream(), or set a raw hook before alling +gps_stream(). + +The old 'W' command has been replaced by ?WATCH. Call gps_stream() +with whatever options you want to set. + +The old 'X' command is gone. Instead, you will see an object of +class DEVICE from the daemon whenever a device is opened or closed. + +The old 'Z' and '$' commands, used by the developers for profiling, +have equivalents, which are presently considered unstable and thus +are undocumented. + +== How the C API and gps_data_t structure has changed == + +gps_open() now takes a third argument and is re-entrant - it's the +old undocumented gps_open_r(). + +The gps_query() entry point is gone. With the new streaming-oriented +wire protocol, it is extremely unwise to assume that the first +transmission from the damon after a command is shipped to it will be +the reponse to command. If you must send explicit +commands to the daemon, use gps_send() and handle the response in +your main event-polling loop -- but beware, as using gps_send() +ties your code to the GPSD wire protocol and is not recommended. + +gps_poll() is renamed gps_read(). + +The client library's reporting structure, struct gpsdata_t, has a new +substructure (struct devconfig_t) named "dev" that groups together +information about the device that shipped the last update to the +client. The members of this structure replace several top-level +struct gpsdata members in older versions. + +Most notably, the gps_device member has been replaced by dev.path. +It is valid after every response with a device tag (DEVICE, TPV, SKY, +AIS, RTCM2, RTCM3). + +The top-level gps_id member is replaced by dev.subtype. This data +should be considered valid only when DEVICEID_SET is on in the +top-level set member. + +The dev members baudrate, parity, stopbits, cycle, mincycle, and +driver_mode replace older top-level members. They should be +considered valid only when DEVICE_SET is on in the top-level set +member. + +The top-level members ndevices and devicelist (used only on the client +side) have been replaced by an array of struct devconfig_t structures. +Data in this structure should be considered valid only when +DEVICELIST_SET is on in the top-level set member. Storage for +pathnames is no longer dynamically allocated, but static; to save +space, it lives in a union with several other substructures. + +The top-level member "satellites" has been changed to +"satellites_visible". The ambiguity in that name had actually induced +a bug or two. + +There is a new substructure, dop, which holds the +dilution-of-precision factors that were previously individual members +of the gpsdata structure. Two new DOPs, xdop and ydop, are available; +these express dilution of precision in longitude and latitude, +respectively. + +There is a gps_waiting() method analogous to the waiting() method in +the Python class -- a way to check if input is waiting from the +daemon. It blocks but takes a timeout value. + +The raw_hook member is gone. + +== C++ client library changes == + +In API version 5, the C++ library defines a single object using RAII. +There are no explicit open() and close() methods; instead, you initialize +the object handing it a host and server, and the connection is shut down +when the object is deleted or goes out of scope. + +== Python client library changes == + +There is a new stream() method analogous to the gps_stream() call in +the C library. As in the C library, the query() method is gone, for +the same reasons. The gps_send() entry point, new in version 3 of the C API, +has had a corresponding Python gps-class send() method all along. + +The pre-existing interface using the poll() method and self.valid is +still available and should work compatibly with a daemon speaking +JSON. One new feature has been added; after a VERSION response (which +a JSON-speaking instance of gpsd should emit when a connection is +opened) the version member of the session will be an object containing +version information. However, data from the new responses (WATCH, +VERSION, AIS, and TIMING in particular) will be available only through +the self.data member. + +The preferred way to use the new gps class is as an iterator +factory, like this: + +---------------------------------------------------------------------- + +for report in gps(mode=WATCH_ENABLE): + process(report) + +---------------------------------------------------------------------- + +See the Client HOWTO for a more detailed example. diff --git a/www/protocol-transition.txt b/www/protocol-transition.txt deleted file mode 100644 index 594d4c87..00000000 --- a/www/protocol-transition.txt +++ /dev/null @@ -1,450 +0,0 @@ -= Moving to GPSD-NG: a Guide for Client Developers = -:description: A Guide for Client Developers moving to GPSD-ND -:keywords: time, GPSD, gpsd, guide, developers, client -Eric S. Raymond -v1.10, Febuary 2011 - -This document is mastered in asciidoc format. If you are reading it in HTML, -you can find the original at the GPSD project website. - -== Why a new protocol? == - -GPSD has moved to a new request/response protocol. This move has been -forced upon us because the old one ran out of namespace. It was -designed with case-insensitive single-character command/response -codes. 25 of 26 ASCII alphabetics were already in use by 2006, and -there have been functional challenges accumulating over the last three -years that will require several more request/response codes - things -like reporting AIS data, reporting raw pseudoranges, and reporting -RTCM3. - -Yes, we could as a desperate expedient have pressed non-alphabetic -printables into service - but the result would have looked like -line noise and only delayed the day of reckoning. Instead, we've -written a new protocol that is upward-compatible with the old one -in that you can mix old and new syntax. - -There were other problems as well. The old command set encouraged -sloppy handling of data by supporting commands that return PVT and -fix-quality information in atomized partial form, without timestamps. - -There was also no way to support returning more than single-line -responses to a client. This was a problem for returning things like -[RINEX] format, which we'd like to be able to do when a device can -report pseudoranges. - -== The transition plan == - -We need to shed the code complexity and overhead of maintaining both -protocols at once. This will happen sooner than it otherwise might -have because gpsd is in part targeted for SBCs and other constrained -environments where shaving a few K off the runtime image can actually -matter. When it comes to keeping the codebase lean and mean, we try -harder. - -The old-protocol support was removed from the daemon in 2.91. Old -protocol will be supported in the client-side library for somewhat -longer, giving your applications a bridge period when they can speak -both old and new protocol -- but the client-side support for old -protocol will be removed when 3.0 ships. - -The 2.92 version, with the new protocol deployed, is be in Lucid -Lynx, the Ubuntu LTS release of April 2010. - -If you follow our transition advice now, you will be able to talk to -all old-protocol and new-protocol versions of the daemon until the 3.0 -shared client library is deployed, at which point your runtime will -silently get smaller but you may no longer be able to use 2.x daemon -versions any more. - -We're counting on binary-package dependencies to make the transition -easier. When you ship a release using the new interface library, -specify the GPSD package at version >= 2.90 to get the new shared -library; then, when the 3.0 interface library is deployed next year, -you shouldn't have to do anything. - -We'll try to make the transition easy, but we cannot guarantee no -problems. The sooner you start adapting your code, the less pain you -are likely to experience. The rest of this document will explain both -theory and practice, and give you specific pointers on how to fix -client code. - -== Virtue is rewarded == - -Since 2004, the way you were *supposed* to be using gpsd was through -one of the client libraries (in C or Python). If you have been doing -it right, you have been telling gpsd to stream data at you with the -'w' command, via application code probably looked something like this: - -------------------------------------------------------------------- - - gpsdata = gps_open(source.server, source.port); - - (void)gps_query(gpsdata, "w+x\n"); - - // This is in your application's main event loop somewhere. - // It polls gpsd for new data. - ... gps_poll(gpsdata) ... - - gps_close() - -------------------------------------------------------------------- - -If you have been virtuous, you need only to make four small changes to -your code. - -. Give gps_open() a third argument that is the address of a struct gps_data_t. -(This interface changed to avoid malloc(3) and make it possible to write -re-entrant client code.) - -. Replace the gps_query() call with: - -------------------------------------------------------------------- -gps_stream(gpsdata, WATCH_ENABLE, NULL) -------------------------------------------------------------------- - -This will tell whatever version of the client library your application -dynamically links to emit what it should under the hood, either old -or new protocol. Unless a target system carries a version of the -libgps shared library different from the gpsd version, everything -should work and continue to work through future updates. - -. Change gps_poll calls to gps_read calls. - -. If you have references to the 'satellites' member of the structure, -those need to change them to 'satellites_visible'. - -There. You're probably done, unless you relied on some parts of -struct gpsdata_t that application developers usually don't or issued -unusual configuration commands. Here are the exceptions: - -* You issued other gps_query() or gps_send() commands, such as "J=1". - If so, you'll need to learn how to say them in the new API (the J - command itself is dead, and you can just remove it entirely). That - is not difficult, and this document will cover what you need to - know. - -* Your application code referenced struct gpsdata_t members that no - longer exist. This will be obvious because your compilation will - fail. Later in this document you will learn how to fix these - problems. - -* You set a per-packet raw hook. This feature is gone; code - can now just look at the response buffer directly. - -* You set a thread hook. We have deleted the thread-hook portion of - the API; for discussion, see "Why threads are gone" below. - -You can probably ignore the rest of this document, unless -either (a) you want to learn about gpsd's new capabilities so you -can use them in creative ways, or (b) you want to caper with unholy glee -as you contemplate the trials awaiting the non-virtuous. - -If you are non-virtuous -- that is, you rolled your own client-side -interface -- you've had years of warning that this choice would -fail to insulate you from protocol details and cost you pain in the -future. That future is now. - -In the remainder of this document we will try to help you minimize the -pain. The main strategy for doing so is to *use libgps* (or its -functional equivalents in languages other than C). Scrap your -hand-rolled interface code! When you use libgps, compatibility issues -become *our* problem to solve rather than *yours*. - -== Binary stability == - -In the past, the GPSD project has not been very good about preserving -stability of the binary structure layout for struct gpsdata_t between -releases. There was a reason for this -- we were very focused -on reducing memory footprint for SBCs and embedded devices, so we -conditioned out various pieces of the strucure depending on what -features were or were not compiled in. - -We're not going to do this any more. It has been pointed out to us -that the friction costs of breaking shared-library compatibility are -higher than we were reckoning. The new layout has no sections -conditionalized; instead, we have moved a number of fields into -a union. From 2.90 on, the structure layout will change rarely, -only at major version bumps. - -== When the bough breaks == - -Even virtuous clients have to worry about version skew. Supposing you -have used libgps and not done anything exotic, you will still have -problems if the client library you linked and the instance of gpsd it -speaks to are using different protocols. - -The possible failure modes are pretty obvious. Transitions are -difficult. We're essentially relying on the distribution integrators -to ship libgps and gpsd updates at the same time, with sane -package dependencies. If that goes smoothly, applications may -not even notice the changes. We can hope... - -== Why threads are gone == - -We have deleted the two functions in the API that managed a -library-internal thread hook. Here's why: - -1. Actual use of it has been at best very rare and possibly nonexistent. - -2. Applications that want location handing to run in a thread are in - a better position to manage thread locks and mutexes themselves - than our client library can possibly be -- after all, the - application knows what all the other threads and mutex locks - are, and our library doesn't. - -3. We don't like to ship code we can't test, we didn't have a - regression test for the thread stuff, and writing one would - have been a painful expenditure of time better spent elsewhere. - -== On not doing things by halves == - -At the same time that pressure has been building to redesign the -protocol, we've been gaining experience in gpsd's application domain -that has made us rethink some of the assumptions behind the old one. - -Since we knew we were going to have a forced compatibility break at the -wire-protocol level anyway, we decided not to do things by halves. One -big break -- in the application model, struct gpsdata_t, and the -wire protocol behind it -- is better than three or four spread out -over a period of time. - -As a result, the new protocol is not an exact superset of the old one. -It reflects a different way of carving up the behavior space in gpsd's -application domain. And the shape of struct gpsdata_t, the -client-side interface structure, has changed in corresponding ways. - -Accordingly, there are three things a client developer will need to -understand about the new protocol. The first is theory: how its model -of the gpsd application domain is different. The second is practice: -how to issue new-style commands and interpret responses. The third, if -you have relied on the structure in a way that now breaks your -compile, is how that structure has changed. - -== How the theory has changed == - -=== Channels are gone === - -In old protocol, when you requested data from the daemon, it would -search for a device supplying the kind of data you had told it you -wanted (GPS, by default) and connect your listening channel to *that -single device*. The association between channel and device was set -when channel was first bound to device and implicit; reports weren't -labeled with the device name. You could request a specific device if -you wanted to. - -In the new protocol, channels are gone. You tell gpsd to stream -reports at you; thereafter, every time an attached GPS or other device -generates a report, you'll get it. There may be multiple devices -reporting; each report will come labeled with the name of the -originating device, and that name will be left in your client -structure along with the rest of the new data. - -In both protocols, when you poll gpsd and get data the client library -takes care of interpreting what comes up the wire from the daemon, and -merges the resulting data into your client structure (struct -gpsdata_t). - -The difference is that before, the API locked you to one device during -the life of the session. Now it potentially has to deal with a *set* -of devices, treated symmetrically. - -There are multiple reasons this change is a good idea. One is that it -makes coping with devices being hotplugged in or out completely -trivial from the client's point of view - it can just choose to ignore -the fact that the device IDs in the reports have changed. Also, the -channel-management hair in the interface goes away. Also, it means -that clients can treat identically the cases where (a) you have one -device reporting different kinds of data (e.g. a marine navigation -system reporting both GPS and AIS) and (b) you have several devices -reporting different kinds of data. - -=== From lockstep to streaming === - -A subtler change has to do with the difference between a lockstep -or conversational interface and a streaming, stateless one. - -In the earliest versions of GPSD, clients requested various pieces of -data by command. After each request, they would need to wait until a -response came back. Then, watcher mode was added. By saying "w+", -you could ask gpsd to stream GPS reports at you whenever it got them. - -In the new protocol, streaming is all there is. Every report coming -up from the daemon is tagged with its device and type. Instead of -issuing commands and then waiting for specific responses, clients -should expect any kind of report at any time and merge it into -client-local storage (libgps does this for you). - -This change is necessary to cope with devices that may send (for -example) mixed GPS and AIS data. In the future, the stream from -gpsd could include other kinds of data, such as the take from -a digital compass, water-temperature sensors, or even aircraft -transponders. - -=== Asynchronous-write handling === - -The old client code had an assumption baked into it that gps_poll() -can do one read call end expect the daemon to hand it an entire -\n-terminated packet. 99.9% of the time this is true, but socket -layers can do some remarkably perverse things. - -In 2.91 and later, what was gps_poll() and is now gps_read() behaves -in a subtly different way. Each call does exactly one read() call as -before, but the incoming data is now buffered; the logic to interpret -the buffer and empty it is called only when the read() contains a \n. -When that happens, the validity flags include the PACKET_SET mask. - -== How the command set has changed == - -If your code issues old-protocol commands 'A', 'D', 'E', 'M', 'P', -'T', 'U', or 'V', it is a wretched hive of scum and villainy that -probably hasn't changed since before the introduction of 'W' in -2004-2005. You are using the oldest single-shot commands and will -have to rewrite your interface significantly, as the new protocol does -not support equivalents. Use libgps. - -If your code issues B, C, or N commands, they need to change to -?DEVICE commands. See the protocol reference for details. - -The 'F' command has no equivalent in 2.90; consider teaching your -client to ignore fix updates when they don't have a specified "device" -or "class" tag, respectively. In 2.91 and later versions, use the "device" -option of the ?WATCH command for similar effect. - -The old 'G' command does not have an equivalent. It would be possible -to implement one, but we probably won't do it unless there is actual -demand (and we don't expect any). - -The old 'I' command has no equivalent. You probably issued it as part -of an initialization string, hoping that a subtype string would later -show up in gps_id so you could post it somewhere. In the new -protocol, when a device sends back subtype information the daemon -ships the client an object of class DEVICE with a device tag and -subtype fields. Watch for that and process appropriately. - -The old 'J' command is dead. gpsd now detects the end of the reporting -cycle reliably and ships on that, buffering data during the individual -reporting cycle. - -The old 'K' command is replaced by ?DEVICES. - -The old 'L' command is replaced by ?VERSION. Note that the daemon now -ships a version response to each client on connect, so it will -probably never be necessary for you to issue a ?VERSION request. - -The old 'M' command has no equivalent. Mode is reported in the TPV response. - -The old 'O' and 'Y' commands are gone. Use ?WATCH and sample the -stream instead. - -The old 'Q' command has no equivalent. DOPs are reported in the SKY response. - -The 'S' command has no equivalent, because it is not well defined what -value should be presented for binary protocols. - -The old 'R' command has been replaced by three optional attributes in -?WATCH. Include the WATCH_RARE, WATCH_RAW and/or WATCH_NMEA masks in -the argument of gps_stream(), or set a raw hook before alling -gps_stream(). - -The old 'W' command has been replaced by ?WATCH. Call gps_stream() -with whatever options you want to set. - -The old 'X' command is gone. Instead, you will see an object of -class DEVICE from the daemon whenever a device is opened or closed. - -The old 'Z' and '$' commands, used by the developers for profiling, -have equivalents, which are presently considered unstable and thus -are undocumented. - -== How the C API and gps_data_t structure has changed == - -gps_open() now takes a third argument and is re-entrant - it's the -old undocumented gps_open_r(). - -The gps_query() entry point is gone. With the new streaming-oriented -wire protocol, it is extremely unwise to assume that the first -transmission from the damon after a command is shipped to it will be -the reponse to command. If you must send explicit -commands to the daemon, use gps_send() and handle the response in -your main event-polling loop -- but beware, as using gps_send() -ties your code to the GPSD wire protocol and is not recommended. - -gps_poll() is renamed gps_read(). - -The client library's reporting structure, struct gpsdata_t, has a new -substructure (struct devconfig_t) named "dev" that groups together -information about the device that shipped the last update to the -client. The members of this structure replace several top-level -struct gpsdata members in older versions. - -Most notably, the gps_device member has been replaced by dev.path. -It is valid after every response with a device tag (DEVICE, TPV, SKY, -AIS, RTCM2, RTCM3). - -The top-level gps_id member is replaced by dev.subtype. This data -should be considered valid only when DEVICEID_SET is on in the -top-level set member. - -The dev members baudrate, parity, stopbits, cycle, mincycle, and -driver_mode replace older top-level members. They should be -considered valid only when DEVICE_SET is on in the top-level set -member. - -The top-level members ndevices and devicelist (used only on the client -side) have been replaced by an array of struct devconfig_t structures. -Data in this structure should be considered valid only when -DEVICELIST_SET is on in the top-level set member. Storage for -pathnames is no longer dynamically allocated, but static; to save -space, it lives in a union with several other substructures. - -The top-level member "satellites" has been changed to -"satellites_visible". The ambiguity in that name had actually induced -a bug or two. - -There is a new substructure, dop, which holds the -dilution-of-precision factors that were previously individual members -of the gpsdata structure. Two new DOPs, xdop and ydop, are available; -these express dilution of precision in longitude and latitude, -respectively. - -There is a gps_waiting() method analogous to the waiting() method in -the Python class -- a way to check if input is waiting from the -daemon. It blocks but takes a timeout value. - -The raw_hook member is gone. - -== C++ client library changes == - -In API version 5, the C++ library defines a single object using RAII. -There are no explicit open() and close() methods; instead, you initialize -the object handing it a host and server, and the connection is shut down -when the object is deleted or goes out of scope. - -== Python client library changes == - -There is a new stream() method analogous to the gps_stream() call in -the C library. As in the C library, the query() method is gone, for -the same reasons. The gps_send() entry point, new in version 3 of the C API, -has had a corresponding Python gps-class send() method all along. - -The pre-existing interface using the poll() method and self.valid is -still available and should work compatibly with a daemon speaking -JSON. One new feature has been added; after a VERSION response (which -a JSON-speaking instance of gpsd should emit when a connection is -opened) the version member of the session will be an object containing -version information. However, data from the new responses (WATCH, -VERSION, AIS, and TIMING in particular) will be available only through -the self.data member. - -The preferred way to use the new gps class is as an iterator -factory, like this: - ----------------------------------------------------------------------- - -for report in gps(mode=WATCH_ENABLE): - process(report) - ----------------------------------------------------------------------- - -See the Client HOWTO for a more detailed example. diff --git a/www/time-service-intro.adoc b/www/time-service-intro.adoc new file mode 100644 index 00000000..0231d1e6 --- /dev/null +++ b/www/time-service-intro.adoc @@ -0,0 +1,351 @@ += Introduction to Time Service = +:description: A primer on precision time sources and services. +:keywords: time, UTC, atomic clock, GPS, NTP +Eric S. Raymond +v1.5, 2015-12-08 + +This document is mastered in asciidoc format. If you are reading it in HTML, +you can find the original at the GPSD project website. + +== Introduction == + +This is a background paper on technological means for high-precision +time measurement. We discuss time source types, relative accuracy, +relative cost, and how those figures of merit have changed in recent +decades. A brief introduction to NTP (Network Time Protocol) is +included. + +== Use cases for precision time service == + +More applications than are commonly realized require precise time; +which, in practice, means time accurate to a tenth of a second or +less. While sub-millisecond time requirements are rare outside of +scientific work and the sharper end of industrial process control, +the range between 0.1sec and 0.001sec has a lot of customers. + +As one large example, the Payment Card Industry (PCI) standards used +by the credit card industry mandate "correct and consistent time" and +gives NTP as an example of qualifying synchronization technology +<>. + +The Financial Industry Regulatory Authority (FINRA) currently requires +that clocks used for business must be synchronized to within one second +of NIST time. The synchronization must occur at least once a day and +before the start of business. A pending rule change <> +proposes to tighten that to just 50 ms. + +Modern cryptographic systems, such as Kerberos, require accurate time. +So do cellular networks and navigation systems for autonomous +vehicles. As these cases suggest, the economic value of +high-precision time is likely to rise significantly in the future. + +There are several equivalent ways to state the precision of a clock. +In the remainder of this introduction we will use "jitter" - the +width of its short-term random variation from its "correct" time - +(commonly Universal Coordinated Time or UTC); usually in nanoseconds +(ns), microsconds (μs), or milliseconds (ms). In these units the +range of interest for most precision time applications is from 100 ms +down to 1000 ns. + +== Time service types == + +A "primary time source" is a very high-precision, very stable +oscillator (popularly called an "atomic clock") used as a source +standard by a national time authority. By international agreement, +the U.S. and other major national time authorities use primary +standards based on electronic transitions between the two hyperfine +energy levels of the ground states of Cesium-133 atoms. + +National time standards are synchronized (essentially, averaged after +removing outliers and consistent errors) to yield an international +reference called Universal Coordinated Time. The US national time +standard, UTC(NIST), normally tracks UTC to within 5 ns <>. + +In practice, the U.S. has another time standard; UTC(USNO), +military clock time propagated through the GPS system. As the skew +between UTC(NIST) and UTC(USNO seldom if ever exceeds 10ns +<> they are for practical purposes identical. + +GPS enables receivers to generate a pulse-per-second +signal ("1PPS" or just "PPS") accurate to the top of the current +UTC second within 50 ns. + +National time standards are also propagated through time radios. In +the U.S., digital time signal is provided by WWVB in Colorado, driven +directly by the NIST (National Institute of Standards and Technology) +master civil time standard. Propagation delay to U.S. receivers +varies but is constant by location and no more than 20 ms; being +fixed, this can be easily compensated out. The jitter added to NIST +time by the WWVB transmission system is about 6 ns <>, +for a total jitter relative to UTC of about 26 ns at the +transmitter. Atmospheric conditions and signal-processing jitter in +the receiver may degrade this considerably, to the tune of 10-100ns +- however some of that is fixed delay that can be compensated out by +knowing your distance from the transmitter. Accuracy is better at night. + +National time authorities may also offer a digital time reference via +landline phone; the U.S.'s has two, supported by NIST and the U.S. +Naval Observatory. NIST has a claimed accuracy of "a few milliseconds" +<>; USNO says 4 ms <>. + +== Clock types == + +A clock, in this context, is a device for delivering an approximation +of a national time standard at a user's location. + +High-end precision clocks are based on rubidium oscillators (close +relatives of the cesium time standards). Less expensive ones are based +on a temperature-compensated crystal oscillator or TCXO, sometimes also +seen as OCXO for "oven-compensated crystal oscillator"; these are more +closely related to the non-temperature-stabilized oscillator in a +quartz-crystal watch. + +Due to frequency drift (induced mainly by temperature variations), all +such clocks need to be periodically conditioned by an external signal +from a time authority. The cost of a clock correlates with its +"holdover" performance - how stable the oscillator's frequency is and +thus how little the time drifts between conditioning signals. + +A "time radio" or "time receiver" is a clock that is conditioned by a +national time radio source. High-end dedicated time receivers can +achieve 50 ns accuracy <>; consumer-grade "atomic clocks" (not +actually atomic at all but using a radio time signal) achieve a much +less impressive 30 ms <> or even as poor as 150 ms <>. +Both are often constrained by siting problems and poor longwave +propagation, leading to frequent loss of signal. In some parts of the +U.S., most notably the Boswash corridor and the southern tip of +Florida, coverage is so intermittent <> as to make the WWVB +signal nearly unusable. The technology works better for smaller, +European-sized countries. + +Time receivers' model designations often include the call sign of +their radio source; for example, a 'WWVB' receiver uses the +U.S. national time radio, a 'DCF77' receiver uses the German national +time radio, an 'MSF' receiver uses the British national time radio, +and a 'JJY' receiver uses the Japanese national time radio. Some time +receivers (especially those made for the European market) can use +multiple stations. A useful table of national time radio stations is +at <>. + +Devices described as "GPS clocks" (or more technically as "GPS +Disciplined Oscillators" or GPSDOs) are conditioned by the 1PPS output +of a GPS receiver. Worst-case accuracy depends on the accuracy of the +1PPS and vendor data sheets commonly claim 100 ns, sometimes even 20 ns. + +The GPS system standard <> Section 3.3.4 specifies that +GPS satellite clock (MSC) from each satellite be within 90 ns of USNO +time to a certainty of one sigma. Adding in GPS satellite position +uncertainty widens the time uncertainty as broadcast from the GPS Sat +to 97 ns at one sigma. Any GPS propagation and reception errors will +add to that uncertainly. Thus one needs to assume a GPSDO will track +USNO time to better than to about 120-200 ns. + +A plain GPS, without a stabilized crystal, can serve as a clock +source. However, it will generally be unable to deliver time at all when +it lacks memory of a previous 3D position fix and current lock on at +least one satellite. In other words, it has no "holdover". (NTP +patches around this by using the system clock for holdover.) + +GPSes actually deliver two times: 1PPS at top of second, and in-band +time expressed in a message packet over the serial or USB link. In +consumer-grade GPSes, 1PPS may not be shipped to the serial connector; +if it is, it becomes a pulse on a handshake line, usually DCD. + +In-band time is usually delivered accurate to the second only and is +shipped with significant and variable delay after 1PPS, typically on +the order of 100 ms. By contrast, 1PPS time output total error will +typically be close to 1μs. + +== Basics of NTP == + +NTP (Network Time Protocol) is a set of protocols that attempts to +synchronize computer clocks across the Internet - ultimately, Universal +Coordinated Time (UTC) as defined by several scale-related atomic clocks +run by national standards institutes. NTP Version 4 is defined in +<>. + +NTP service daemons running on each host do clock synchronization in +the presence of variable network latency by monitoring those delays in +real time and passing around messages that say, essentially, "I +received your request at time X, I'm sending the reply at time Y and +the propagation delay to my source of time is Z". Each daemon then +uses rather complex algorithms that we won't attempt to describe here +to digest incoming messages into a composite "NTP time". + +NTP conditions your system clock by noticing how your system clock time +differs from deduced NTP time, then speeding up or slowing down your +clock's tick rate until it is synchronized. These tick-rate changes +are usually extremely small, much too small for a human or even most +software timing loops to ever notice. But large changes are possible. + +NTP's technique exploits the fact that while the quartz crystals used +in PC clocks are not very accurate, they are quite stable - that is, +their frequency drift in response to environmental changes is slow. + +Most computers are just NTP clients. They send NTP requests to a set +of servers and use the replies to adjust the local clock. It is +generally expected that NTP clients will have an accuracy (that is, +maximum divergence from the master atomic clock) of of "a few tens of +milliseconds" <>; however, problems such as asymmetric +routing, bufferbloat, or large time jitter (especially likely on cable +networks) can degrade accuracy to around 100 ms and even worse in +extreme cases. + +Some NTP hosts are time *servers*. They respond to NTP clients with +time read from high-precision reference clocks (often abbreviated +"refclocks") synchronized to national time standards. The refclocks +are all the kinds of precision time source discussed earlier in this +document. + +You will hear time service people speak of "Stratum 0" (the reference +clocks) "Stratum 1" (NTP servers directly connected to reference +clocks) and "Stratum 2" (servers that get time from Stratum +1). Stratum 3 servers redistribute time from Stratum 2, and so +forth. There are defined higher strata up to 15, but you will probably +never see a public time server higher than Stratum 3 or 4. + +Jitter induced by variable WAN propagation delays +(including variations in switch latency and routing) makes it +impractical to try to improve the accuracy of NTP time to much better +than the "a few tens of milliseconds" of <>. + +== Cost-effective clocks == + +There is about three orders of magnitude between the best achievable +wide-area-network accuracy and even the lowest-end GPS-constrained +clock or time radio. Of all the time sources described here, the only +one not precise enough to drive WAN NTP is in-band time from a GPS +without 1PPS footnote:[Actually, a non-1PPS GPS with sufficiently +clever firmware can be good enough - but they almost never are in +practice, and never in consumer-grade hardware.]. + +Since the year 2000 GPSes have drastically decreased in price and +improved in performance. For time-service purposes the important +performance metric is weak-signal performance and ability to operate +indoors. + +A 1PPS-capable plain GPS that can operate reliably near a window is +for NTP purposes nearly as good as a time radio or GPS clock, and +orders of magnitude less expensive. Even the USB 1.1 polling interval +of 1 ms does not introduce a disqualifying amount of jitter for WAN +service. + +LANs are a different matter. Because their propagation delays are +lower and less variable, NTP can do about two orders of magnitude better +in this context, easily sustaining 1 ms accuracy. The combination of +NTP and <> can achieve LAN time service another two orders of +magnitude better. + +GPS clocks and time radios remain, therefore, cost effective for +driving NTP over LAN. This is significant in many scientific, +industrial, and government deployments. + +While pressure from plain GPSes has eroded the competitiveness of both +GPS clocks and time radios, time radios have suffered more. While +theoretically more accurate than GPS clocks, they have not improved in +weak-signal performance in the dramatic way GPSes and GPS clocks +have; they remain finicky and nearly as vulnerable to siting and +skyview problems as the GPSes of decades ago. + +Furthermore, the U.S. radio-clock industry was impacted when <> +changed its modulation scheme at 2012-10-29T15:00:00Z. This didn't +affect consumer-grade "atomic" clocks, which resynchronize once a day +and don't use the fine details of the signal, but it obsolesced all +the high-end equipment that conditioned on shorter time scales. At +least one major timing-systems vendor (Spectracom) bailed out of the +time-radio market entirely, and it is not clear there are any high-end +vendors at all left in the U.S. + +== Summary == + +Some figures in this table are from <> and are explained +in more detail there. + +.Summary of worst-case deviation from UTC +|============================================================== +|National primary time standard | 20 ns +|WWVB time radio broadcast | 26 ns +|GPS 1PPS top of second | 50 ns +|Dedicated time receiver | 50 ns +|GPS-constrained clock | 100 ns +| | +|1PPS delivered by OS kernel | 1 μs (1000 ns) +|Serial 1PPS | 5 μs (5000 ns) +|1PPS over USB 1.1 | 1 ms (1000000 ns) +|1PPS over USB 2.0 | 100 μs (100000 ns) +| | +|NIST/USNO modem time | 4 ms (4000000 ns) +|Consumer-grade time radio | 30-150 ms +|Normal accuracy of NTP | ~ 30 ms (3000000 ns) +|Jitter of in-band GPS time | > 100 ms (100000000 ns) +|============================================================== + +== Further Reading == + +You can find a practical how-to on setting up a local Stratum 1 time +server using GPSD and an inexpensive GPS at <>. + +== References == + +[bibliography] + +- [[[PCI3]]] https://www.pcisecuritystandards.org/documents/PCI_DSS_v3.pdf[Requirements and Security Assessment +Procedures] + +- [[[FINRA_14-47]]] +http://www.finra.org/sites/default/files/notice_doc_file_ref/Notice_Regulatory_14-47.pdf[14-47] + +- [[[RFC-5905]]] http://www.ietf.org/rfc/rfc5905.txt[Network Time Protocol Version 4: Protocol and Algorithms Specification] + +- [[[WWVBPRECION]]] http://tf.nist.gov/timefreq/pubs/bulletin/pdf/1999OCT_TF_BULLETIN.pdf[NIST +Time and Frequency Bulletin NISTIR 5082-10] + +- [[[BIPM-T]]] ftp://ftp2.bipm.org/pub/tai/publication/cirt/[See latest Circular T from BIPM] + +- [[[WWVBMAP]]] http://tf.nist.gov/stations/wwvbcoverage.htm[WWVB Coverage Area] + +- [[[SPECTRUMWIKI]]] http://www.spectrumwiki.com/wiki/DisplayEntry.aspx?DisplyId=51[Low Frequency Time Signals] + +- [[[IS-GPS-200G]]] http://www.gps.gov/technical/icwg/IS-GPS-200G.pdf[IS-GPS-200G] + +- [[[TIMESCALE]] http://www.nist.gov/pml/div688/grp50/nistusno.cfm[NIST Time Scale Data Archive] + +- [[[ACTS1]]] http://www.nist.gov/pml/div688/grp40/acts.cfm[NIST Automated Computer Time Service (ACTS)] + +- [[[ACTS2]]] http://tycho.usno.navy.mil/modem_time.html[USNO Master +Clock via Modem] + +- [[[RADIO]]] http://en.wikipedia.org/wiki/Radio_clock[Radio clock] + +- [[[HARCC]]] http://tf.nist.gov/general/pdf/2429.pdf[How Accurate is a Radio Controlled Clock?] + +- [[[JUNGHANS]]] http://www.leapsecond.com/pages/Junghans/[Junghans Solar WWVB watch] + +- [[[PTP]]] http://en.wikipedia.org/wiki/Precision_Time_Protocol[PTP] + +- [[[GPSD-HOWTO]]] link:gpsd-time-service-howto.html[GPSD Time Service HOWTO] + +- [[WWVB]] http://www.nist.gov/pml/div688/grp40/wwvb.cfm[NIST Radio Station WWVB] + +== History == + +v1.0, 2015-03-10:: + Initial version. + +v1.1, 2015-03-11:: + Lots of tiny corrections from G+ and the blog. Use the NTP + accuracy estimate from RFC 5905. + +v1.2, 2015-03-15:: + Clarifying language, proof-reading, and minor corrections. + +v1.3, 2015-03-16:: + Text polishing, terminological cleanup. + +v1.4, 2015-07-11:: + Text polishing, note upcoming change in FINRA, more about GPSDO precision. + +v1.5, 2015-12-10:: + Fix typo in WWVB delay figure and date of modulation change. + +//end diff --git a/www/time-service-intro.txt b/www/time-service-intro.txt deleted file mode 100644 index 0231d1e6..00000000 --- a/www/time-service-intro.txt +++ /dev/null @@ -1,351 +0,0 @@ -= Introduction to Time Service = -:description: A primer on precision time sources and services. -:keywords: time, UTC, atomic clock, GPS, NTP -Eric S. Raymond -v1.5, 2015-12-08 - -This document is mastered in asciidoc format. If you are reading it in HTML, -you can find the original at the GPSD project website. - -== Introduction == - -This is a background paper on technological means for high-precision -time measurement. We discuss time source types, relative accuracy, -relative cost, and how those figures of merit have changed in recent -decades. A brief introduction to NTP (Network Time Protocol) is -included. - -== Use cases for precision time service == - -More applications than are commonly realized require precise time; -which, in practice, means time accurate to a tenth of a second or -less. While sub-millisecond time requirements are rare outside of -scientific work and the sharper end of industrial process control, -the range between 0.1sec and 0.001sec has a lot of customers. - -As one large example, the Payment Card Industry (PCI) standards used -by the credit card industry mandate "correct and consistent time" and -gives NTP as an example of qualifying synchronization technology -<>. - -The Financial Industry Regulatory Authority (FINRA) currently requires -that clocks used for business must be synchronized to within one second -of NIST time. The synchronization must occur at least once a day and -before the start of business. A pending rule change <> -proposes to tighten that to just 50 ms. - -Modern cryptographic systems, such as Kerberos, require accurate time. -So do cellular networks and navigation systems for autonomous -vehicles. As these cases suggest, the economic value of -high-precision time is likely to rise significantly in the future. - -There are several equivalent ways to state the precision of a clock. -In the remainder of this introduction we will use "jitter" - the -width of its short-term random variation from its "correct" time - -(commonly Universal Coordinated Time or UTC); usually in nanoseconds -(ns), microsconds (μs), or milliseconds (ms). In these units the -range of interest for most precision time applications is from 100 ms -down to 1000 ns. - -== Time service types == - -A "primary time source" is a very high-precision, very stable -oscillator (popularly called an "atomic clock") used as a source -standard by a national time authority. By international agreement, -the U.S. and other major national time authorities use primary -standards based on electronic transitions between the two hyperfine -energy levels of the ground states of Cesium-133 atoms. - -National time standards are synchronized (essentially, averaged after -removing outliers and consistent errors) to yield an international -reference called Universal Coordinated Time. The US national time -standard, UTC(NIST), normally tracks UTC to within 5 ns <>. - -In practice, the U.S. has another time standard; UTC(USNO), -military clock time propagated through the GPS system. As the skew -between UTC(NIST) and UTC(USNO seldom if ever exceeds 10ns -<> they are for practical purposes identical. - -GPS enables receivers to generate a pulse-per-second -signal ("1PPS" or just "PPS") accurate to the top of the current -UTC second within 50 ns. - -National time standards are also propagated through time radios. In -the U.S., digital time signal is provided by WWVB in Colorado, driven -directly by the NIST (National Institute of Standards and Technology) -master civil time standard. Propagation delay to U.S. receivers -varies but is constant by location and no more than 20 ms; being -fixed, this can be easily compensated out. The jitter added to NIST -time by the WWVB transmission system is about 6 ns <>, -for a total jitter relative to UTC of about 26 ns at the -transmitter. Atmospheric conditions and signal-processing jitter in -the receiver may degrade this considerably, to the tune of 10-100ns -- however some of that is fixed delay that can be compensated out by -knowing your distance from the transmitter. Accuracy is better at night. - -National time authorities may also offer a digital time reference via -landline phone; the U.S.'s has two, supported by NIST and the U.S. -Naval Observatory. NIST has a claimed accuracy of "a few milliseconds" -<>; USNO says 4 ms <>. - -== Clock types == - -A clock, in this context, is a device for delivering an approximation -of a national time standard at a user's location. - -High-end precision clocks are based on rubidium oscillators (close -relatives of the cesium time standards). Less expensive ones are based -on a temperature-compensated crystal oscillator or TCXO, sometimes also -seen as OCXO for "oven-compensated crystal oscillator"; these are more -closely related to the non-temperature-stabilized oscillator in a -quartz-crystal watch. - -Due to frequency drift (induced mainly by temperature variations), all -such clocks need to be periodically conditioned by an external signal -from a time authority. The cost of a clock correlates with its -"holdover" performance - how stable the oscillator's frequency is and -thus how little the time drifts between conditioning signals. - -A "time radio" or "time receiver" is a clock that is conditioned by a -national time radio source. High-end dedicated time receivers can -achieve 50 ns accuracy <>; consumer-grade "atomic clocks" (not -actually atomic at all but using a radio time signal) achieve a much -less impressive 30 ms <> or even as poor as 150 ms <>. -Both are often constrained by siting problems and poor longwave -propagation, leading to frequent loss of signal. In some parts of the -U.S., most notably the Boswash corridor and the southern tip of -Florida, coverage is so intermittent <> as to make the WWVB -signal nearly unusable. The technology works better for smaller, -European-sized countries. - -Time receivers' model designations often include the call sign of -their radio source; for example, a 'WWVB' receiver uses the -U.S. national time radio, a 'DCF77' receiver uses the German national -time radio, an 'MSF' receiver uses the British national time radio, -and a 'JJY' receiver uses the Japanese national time radio. Some time -receivers (especially those made for the European market) can use -multiple stations. A useful table of national time radio stations is -at <>. - -Devices described as "GPS clocks" (or more technically as "GPS -Disciplined Oscillators" or GPSDOs) are conditioned by the 1PPS output -of a GPS receiver. Worst-case accuracy depends on the accuracy of the -1PPS and vendor data sheets commonly claim 100 ns, sometimes even 20 ns. - -The GPS system standard <> Section 3.3.4 specifies that -GPS satellite clock (MSC) from each satellite be within 90 ns of USNO -time to a certainty of one sigma. Adding in GPS satellite position -uncertainty widens the time uncertainty as broadcast from the GPS Sat -to 97 ns at one sigma. Any GPS propagation and reception errors will -add to that uncertainly. Thus one needs to assume a GPSDO will track -USNO time to better than to about 120-200 ns. - -A plain GPS, without a stabilized crystal, can serve as a clock -source. However, it will generally be unable to deliver time at all when -it lacks memory of a previous 3D position fix and current lock on at -least one satellite. In other words, it has no "holdover". (NTP -patches around this by using the system clock for holdover.) - -GPSes actually deliver two times: 1PPS at top of second, and in-band -time expressed in a message packet over the serial or USB link. In -consumer-grade GPSes, 1PPS may not be shipped to the serial connector; -if it is, it becomes a pulse on a handshake line, usually DCD. - -In-band time is usually delivered accurate to the second only and is -shipped with significant and variable delay after 1PPS, typically on -the order of 100 ms. By contrast, 1PPS time output total error will -typically be close to 1μs. - -== Basics of NTP == - -NTP (Network Time Protocol) is a set of protocols that attempts to -synchronize computer clocks across the Internet - ultimately, Universal -Coordinated Time (UTC) as defined by several scale-related atomic clocks -run by national standards institutes. NTP Version 4 is defined in -<>. - -NTP service daemons running on each host do clock synchronization in -the presence of variable network latency by monitoring those delays in -real time and passing around messages that say, essentially, "I -received your request at time X, I'm sending the reply at time Y and -the propagation delay to my source of time is Z". Each daemon then -uses rather complex algorithms that we won't attempt to describe here -to digest incoming messages into a composite "NTP time". - -NTP conditions your system clock by noticing how your system clock time -differs from deduced NTP time, then speeding up or slowing down your -clock's tick rate until it is synchronized. These tick-rate changes -are usually extremely small, much too small for a human or even most -software timing loops to ever notice. But large changes are possible. - -NTP's technique exploits the fact that while the quartz crystals used -in PC clocks are not very accurate, they are quite stable - that is, -their frequency drift in response to environmental changes is slow. - -Most computers are just NTP clients. They send NTP requests to a set -of servers and use the replies to adjust the local clock. It is -generally expected that NTP clients will have an accuracy (that is, -maximum divergence from the master atomic clock) of of "a few tens of -milliseconds" <>; however, problems such as asymmetric -routing, bufferbloat, or large time jitter (especially likely on cable -networks) can degrade accuracy to around 100 ms and even worse in -extreme cases. - -Some NTP hosts are time *servers*. They respond to NTP clients with -time read from high-precision reference clocks (often abbreviated -"refclocks") synchronized to national time standards. The refclocks -are all the kinds of precision time source discussed earlier in this -document. - -You will hear time service people speak of "Stratum 0" (the reference -clocks) "Stratum 1" (NTP servers directly connected to reference -clocks) and "Stratum 2" (servers that get time from Stratum -1). Stratum 3 servers redistribute time from Stratum 2, and so -forth. There are defined higher strata up to 15, but you will probably -never see a public time server higher than Stratum 3 or 4. - -Jitter induced by variable WAN propagation delays -(including variations in switch latency and routing) makes it -impractical to try to improve the accuracy of NTP time to much better -than the "a few tens of milliseconds" of <>. - -== Cost-effective clocks == - -There is about three orders of magnitude between the best achievable -wide-area-network accuracy and even the lowest-end GPS-constrained -clock or time radio. Of all the time sources described here, the only -one not precise enough to drive WAN NTP is in-band time from a GPS -without 1PPS footnote:[Actually, a non-1PPS GPS with sufficiently -clever firmware can be good enough - but they almost never are in -practice, and never in consumer-grade hardware.]. - -Since the year 2000 GPSes have drastically decreased in price and -improved in performance. For time-service purposes the important -performance metric is weak-signal performance and ability to operate -indoors. - -A 1PPS-capable plain GPS that can operate reliably near a window is -for NTP purposes nearly as good as a time radio or GPS clock, and -orders of magnitude less expensive. Even the USB 1.1 polling interval -of 1 ms does not introduce a disqualifying amount of jitter for WAN -service. - -LANs are a different matter. Because their propagation delays are -lower and less variable, NTP can do about two orders of magnitude better -in this context, easily sustaining 1 ms accuracy. The combination of -NTP and <> can achieve LAN time service another two orders of -magnitude better. - -GPS clocks and time radios remain, therefore, cost effective for -driving NTP over LAN. This is significant in many scientific, -industrial, and government deployments. - -While pressure from plain GPSes has eroded the competitiveness of both -GPS clocks and time radios, time radios have suffered more. While -theoretically more accurate than GPS clocks, they have not improved in -weak-signal performance in the dramatic way GPSes and GPS clocks -have; they remain finicky and nearly as vulnerable to siting and -skyview problems as the GPSes of decades ago. - -Furthermore, the U.S. radio-clock industry was impacted when <> -changed its modulation scheme at 2012-10-29T15:00:00Z. This didn't -affect consumer-grade "atomic" clocks, which resynchronize once a day -and don't use the fine details of the signal, but it obsolesced all -the high-end equipment that conditioned on shorter time scales. At -least one major timing-systems vendor (Spectracom) bailed out of the -time-radio market entirely, and it is not clear there are any high-end -vendors at all left in the U.S. - -== Summary == - -Some figures in this table are from <> and are explained -in more detail there. - -.Summary of worst-case deviation from UTC -|============================================================== -|National primary time standard | 20 ns -|WWVB time radio broadcast | 26 ns -|GPS 1PPS top of second | 50 ns -|Dedicated time receiver | 50 ns -|GPS-constrained clock | 100 ns -| | -|1PPS delivered by OS kernel | 1 μs (1000 ns) -|Serial 1PPS | 5 μs (5000 ns) -|1PPS over USB 1.1 | 1 ms (1000000 ns) -|1PPS over USB 2.0 | 100 μs (100000 ns) -| | -|NIST/USNO modem time | 4 ms (4000000 ns) -|Consumer-grade time radio | 30-150 ms -|Normal accuracy of NTP | ~ 30 ms (3000000 ns) -|Jitter of in-band GPS time | > 100 ms (100000000 ns) -|============================================================== - -== Further Reading == - -You can find a practical how-to on setting up a local Stratum 1 time -server using GPSD and an inexpensive GPS at <>. - -== References == - -[bibliography] - -- [[[PCI3]]] https://www.pcisecuritystandards.org/documents/PCI_DSS_v3.pdf[Requirements and Security Assessment -Procedures] - -- [[[FINRA_14-47]]] -http://www.finra.org/sites/default/files/notice_doc_file_ref/Notice_Regulatory_14-47.pdf[14-47] - -- [[[RFC-5905]]] http://www.ietf.org/rfc/rfc5905.txt[Network Time Protocol Version 4: Protocol and Algorithms Specification] - -- [[[WWVBPRECION]]] http://tf.nist.gov/timefreq/pubs/bulletin/pdf/1999OCT_TF_BULLETIN.pdf[NIST -Time and Frequency Bulletin NISTIR 5082-10] - -- [[[BIPM-T]]] ftp://ftp2.bipm.org/pub/tai/publication/cirt/[See latest Circular T from BIPM] - -- [[[WWVBMAP]]] http://tf.nist.gov/stations/wwvbcoverage.htm[WWVB Coverage Area] - -- [[[SPECTRUMWIKI]]] http://www.spectrumwiki.com/wiki/DisplayEntry.aspx?DisplyId=51[Low Frequency Time Signals] - -- [[[IS-GPS-200G]]] http://www.gps.gov/technical/icwg/IS-GPS-200G.pdf[IS-GPS-200G] - -- [[[TIMESCALE]] http://www.nist.gov/pml/div688/grp50/nistusno.cfm[NIST Time Scale Data Archive] - -- [[[ACTS1]]] http://www.nist.gov/pml/div688/grp40/acts.cfm[NIST Automated Computer Time Service (ACTS)] - -- [[[ACTS2]]] http://tycho.usno.navy.mil/modem_time.html[USNO Master -Clock via Modem] - -- [[[RADIO]]] http://en.wikipedia.org/wiki/Radio_clock[Radio clock] - -- [[[HARCC]]] http://tf.nist.gov/general/pdf/2429.pdf[How Accurate is a Radio Controlled Clock?] - -- [[[JUNGHANS]]] http://www.leapsecond.com/pages/Junghans/[Junghans Solar WWVB watch] - -- [[[PTP]]] http://en.wikipedia.org/wiki/Precision_Time_Protocol[PTP] - -- [[[GPSD-HOWTO]]] link:gpsd-time-service-howto.html[GPSD Time Service HOWTO] - -- [[WWVB]] http://www.nist.gov/pml/div688/grp40/wwvb.cfm[NIST Radio Station WWVB] - -== History == - -v1.0, 2015-03-10:: - Initial version. - -v1.1, 2015-03-11:: - Lots of tiny corrections from G+ and the blog. Use the NTP - accuracy estimate from RFC 5905. - -v1.2, 2015-03-15:: - Clarifying language, proof-reading, and minor corrections. - -v1.3, 2015-03-16:: - Text polishing, terminological cleanup. - -v1.4, 2015-07-11:: - Text polishing, note upcoming change in FINRA, more about GPSDO precision. - -v1.5, 2015-12-10:: - Fix typo in WWVB delay figure and date of modulation change. - -//end -- cgit v1.2.1