summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2011-04-15 11:59:26 -0400
committerEric S. Raymond <esr@thyrsus.com>2011-04-15 11:59:26 -0400
commit0e55585a6417ccb4a25c27203955fa6a4db1d553 (patch)
tree9b1a72e0d6776491cae9e5b4ccc7ad3863258772
parentc7cddac1fe760e5698cdfa3aaf359948cf32d16a (diff)
downloadgpsd-0e55585a6417ccb4a25c27203955fa6a4db1d553.tar.gz
Support AISmessage type 27.
Also, revise the website uploader so it knows about scons.
-rw-r--r--ais_json.c2
-rwxr-xr-xdevtools/ais.py21
-rw-r--r--driver_aivdm.c22
-rw-r--r--gps.h16
-rw-r--r--gpsd_json.c14
-rw-r--r--gpsd_json.xml4
-rw-r--r--jsongen.py.in16
-rw-r--r--www/AIVDM.txt72
-rwxr-xr-xwww/upload2
9 files changed, 146 insertions, 23 deletions
diff --git a/ais_json.c b/ais_json.c
index a9312d34..29e1628c 100644
--- a/ais_json.c
+++ b/ais_json.c
@@ -141,6 +141,8 @@ int json_ais_read(const char *buf,
status = json_read_object(buf, json_ais25, endptr);
} else if (strstr(buf, "\"type\":26,") != NULL) {
status = json_read_object(buf, json_ais26, endptr);
+ } else if (strstr(buf, "\"type\":27,") != NULL) {
+ status = json_read_object(buf, json_ais27, endptr);
} else {
if (endptr != NULL)
*endptr = NULL;
diff --git a/devtools/ais.py b/devtools/ais.py
index a8799195..29530708 100755
--- a/devtools/ais.py
+++ b/devtools/ais.py
@@ -19,7 +19,7 @@
# we have test data.
#
# Decoding for 1-15, 18-21, and 24 have been tested against live data.
-# Decoding for 16-17, 22-23, and 25-26 have not.
+# Decoding for 16-17, 22-23, and 25-27 have not.
# Here are the pseudoinstructions in the pseudolanguage.
@@ -672,6 +672,22 @@ type25 = (
# No type 26 handling yet, we'd need new machinery to constrain how many
# bits the data spec eats in order to recover the radio bits after it.
+type27 = (
+ bitfield("accuracy", 1, 'unsigned', None, "Position Accuracy"),
+ bitfield("raim", 1, 'unsigned', None, "RAIM flag"),
+ bitfield("status", 4, 'unsigned', 0, "Navigation Status",
+ formatter=cnb_status_legends),
+ bitfield("lon", 18, 'signed', 0x1a838, "Longitude",
+ formatter=short_latlon_format),
+ bitfield("lat", 17, 'signed', 0xd548, "Latitude",
+ formatter=short_latlon_format),
+ bitfield("speed", 6, 'unsigned', 63, "Speed Over Ground",
+ formatter=cnb_speed_format),
+ bitfield("course", 9, 'unsigned', 511, "Course Over Ground"),
+ bitfield("GNSS", 1, 'unsigned', None, "GNSS flag"),
+ spare(1),
+ )
+
aivdm_decode = (
bitfield('msgtype', 6, 'unsigned', 0, "Message Type",
validator=lambda n: n > 0 and n <= 26),
@@ -683,7 +699,7 @@ aivdm_decode = (
type10, type4, type12, type7, type14,
type15, type16, type17, type18, type19,
type20, type21, type22, type23, type24,
- type25]),
+ type25, None, type27]),
)
# Length ranges. We use this for integrity checking.
@@ -715,6 +731,7 @@ lengths = {
24: (160, 168),
25: 168,
26: (60, 1004),
+ 27, 96,
}
field_groups = (
diff --git a/driver_aivdm.c b/driver_aivdm.c
index 91b94cc0..c2824026 100644
--- a/driver_aivdm.c
+++ b/driver_aivdm.c
@@ -240,7 +240,7 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type1.raim = UBITS(148, 1)!=0;
ais->type1.radio = UBITS(149, 20);
gpsd_report(LOG_INF,
- "Nav=%d TURN=%d SPEED=%d Q=%d Lon=%d Lat=%d COURSE=%d TH=%d Sec=%d\n",
+ "Nav=%d TURN=%d SOG=%d Q=%d Lon=%d Lat=%d COG=%d TH=%d Sec=%d\n",
ais->type1.status,
ais->type1.turn,
ais->type1.speed,
@@ -462,7 +462,7 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type9.raim = UBITS(147, 1)!=0;
ais->type9.radio = UBITS(148, 19);
gpsd_report(LOG_INF,
- "Alt=%d SPEED=%d Q=%d Lon=%d Lat=%d COURSE=%d Sec=%d\n",
+ "Alt=%d SOG=%d Q=%d Lon=%d Lat=%d COG=%d Sec=%d\n",
ais->type9.alt,
ais->type9.speed,
(uint)ais->type9.accuracy,
@@ -883,6 +883,24 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type26.app_id,
ais->type26.bitcount);
break;
+ case 27: /* Long Range AIS Broadcast message */
+ ais->type27.accuracy = (bool)UBITS(38, 1);
+ ais->type27.raim = UBITS(39, 1)!=0;
+ ais->type27.status = UBITS(40, 4);
+ ais->type27.lon = SBITS(44, 18);
+ ais->type27.lat = SBITS(62, 17);
+ ais->type27.speed = UBITS(79, 6);
+ ais->type27.course = UBITS(85, 9);
+ ais->type27.gnss = (bool)UBITS(94, 1);
+ gpsd_report(LOG_INF,
+ "Nav=%d SOG=%d Q=%d Lon=%d Lat=%d COG=%d\n",
+ ais->type27.status,
+ ais->type27.speed,
+ (uint)ais->type27.accuracy,
+ ais->type27.lon,
+ ais->type27.lat,
+ ais->type27.course);
+ break;
default:
gpsd_report(LOG_INF, "\n");
gpsd_report(LOG_ERROR, "Unparsed AIVDM message type %d.\n",ais->type);
diff --git a/gps.h b/gps.h
index 87d0d9fd..0e817677 100644
--- a/gps.h
+++ b/gps.h
@@ -1221,6 +1221,22 @@ struct ais_t
char bitdata[(AIS_TYPE26_BINARY_MAX + 7) / 8];
unsigned int radio; /* radio status bits */
} type26;
+ /* Type 27 - Long Range AIS Broadcast message */
+ struct {
+ bool accuracy; /* position accuracy */
+ bool raim; /* RAIM flag */
+ unsigned int status; /* navigation status */
+#define AIS_LONGRANGE_LATLON_SCALE 600.0
+ int lon; /* longitude */
+#define AIS_LONGRANGE_LON_NOT_AVAILABLE 0x1a838
+ int lat; /* latitude */
+#define AIS_LONGRANGE_LAT_NOT_AVAILABLE 0xd548
+ unsigned int speed; /* speed over ground in deciknots */
+#define AIS_LONGRANGE_SPEED_NOT_AVAILABLE 63
+ unsigned int course; /* course over ground */
+#define AIS_LONGRANGE_COURSE_NOT_AVAILABLE 511
+ bool gnss; /* are we reporting GNSS position? */
+ } type27;
};
};
diff --git a/gpsd_json.c b/gpsd_json.c
index 1d00b332..bf6c094a 100644
--- a/gpsd_json.c
+++ b/gpsd_json.c
@@ -2154,6 +2154,20 @@ void json_aivdm_dump(const struct ais_t *ais,
(ais->type26.bitcount + 7) / 8),
ais->type26.radio);
break;
+ case 27: /* Long Range AIS Broadcast message */
+ (void)snprintf(buf + strlen(buf), buflen - strlen(buf),
+ "\"status\":\"%s\","
+ "\"accuracy\":%s,\"lon\":%.1f,\"lat\":%.1f,"
+ "\"speed\":%u,\"course\":%u,raim\":%s,\"gnss\":%s}\r\n",
+ nav_legends[ais->type27.status],
+ JSON_BOOL(ais->type27.accuracy),
+ ais->type27.lon / AIS_LONGRANGE_LATLON_SCALE,
+ ais->type27.lat / AIS_LONGRANGE_LATLON_SCALE,
+ ais->type27.speed,
+ ais->type27.course,
+ JSON_BOOL(ais->type27.raim),
+ JSON_BOOL(ais->type27.gnss));
+ break;
default:
if (buf[strlen(buf) - 1] == ',')
buf[strlen(buf) - 1] = '\0';
diff --git a/gpsd_json.xml b/gpsd_json.xml
index 2e0bbee5..c9030881 100644
--- a/gpsd_json.xml
+++ b/gpsd_json.xml
@@ -2212,9 +2212,9 @@ performed for JSON output. Latitudes and longitudes are scaled to
decimal degrees rather than the native AIS unit of 1/10000th of a
minute of arc. Ship (but not air) speeds are scaled to knots rather
than tenth-of-knot units. Navigation status and positioning-system
-type are dumped as text strings rather than IAS numeric codes. Rate of
+type are dumped as text strings rather than AIS numeric codes. Rate of
turn may appear as "nan" if is unavailable, or as one of the strings
-"fastright" or "fastleft" if it is out of the IAS encoding range;
+"fastright" or "fastleft" if it is out of the AIS encoding range;
otherwise it is quadratically mapped back to the turn sensor number in
degrees per minute. Vessel draughts are converted to decimal meters
rather than native AIS decimeters. Various other scaling conversions
diff --git a/jsongen.py.in b/jsongen.py.in
index d8ff6d09..17aceed4 100644
--- a/jsongen.py.in
+++ b/jsongen.py.in
@@ -394,6 +394,22 @@ ais_specs = (
),
"stringbuffered":("data",),
},
+ {
+ "initname" : "json_ais27",
+ "header": "\tAIS_HEADER,",
+ "structname": "ais->type27",
+ "fieldmap":(
+ # fieldname type default
+ ('status', 'uinteger', '0'),
+ ('speed', 'uinteger', 'AIS_LONGRANGE_SPEED_NOT_AVAILABLE'),
+ ('accuracy', 'boolean', 'false'),
+ ('lon', 'integer', 'AIS_LONGRANGE_LON_NOT_AVAILABLE'),
+ ('lat', 'integer', 'AIS_LONGRANGE_LAT_NOT_AVAILABLE'),
+ ('course', 'uinteger', 'AIS_LONGRANGE_COURSE_NOT_AVAILABLE'),
+ ('raim', 'boolean', 'false'),
+ ('gnss', 'boolean', 'true'),
+ ),
+ },
)
diff --git a/www/AIVDM.txt b/www/AIVDM.txt
index 383ef9ae..0dfe589c 100644
--- a/www/AIVDM.txt
+++ b/www/AIVDM.txt
@@ -51,19 +51,20 @@ technically difficult and impeded by legal barriers.
ITU Recommendation M.1371, "Technical Characteristics for a Universal
Shipborne Automatic Identification System Using Time Division Multiple
-Access" <<ITU1371>>, issued in 2001, describes the bit-level format of
-AIS radio messages. This standard was proprietary and expensive for
-a long time. It became available for free download, apparently at
-some point in 2011, well after most of ths document was assembled.
+Access" <<ITU1371>>, issued in 2001, first described the bit-level
+format of AIS radio messages. This standard was proprietary and
+expensive. 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 is expanded and clarified by "IALA Technical
+ITU-R M.1371 was expanded and clarified by "IALA Technical
Clarifications on Recommendation ITU-R M.1371-1" <<IALA>>, which
is freely available.
-There have been two minor revisions of ITU-R M.1371 since it was
+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". I have not
-seen these either, but have been passed information on them.
+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
@@ -96,6 +97,8 @@ ITU-1371-3.
Descriptions of messages 25 and 26 are based on AIS transceiver vendor
documentation forwarded to me by a source wishing to remain anonymous.
+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
@@ -130,7 +133,7 @@ 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-26.
+* Sample sentences of types 16-17, 22-23, and 25-27.
* Sample sentences of type 6 and 8 conforming to <<IMO236>> and <<IMO289>>.
@@ -418,6 +421,7 @@ types are as follows:
|24 |Class B CS Static Data Report
|25 |Binary Message, Single Slot
|26 |Binary Message, Multiple Slot
+|27 |Position report for long-range applications
|======================================================
In normal operation, an AIS transceiver will broadcast a position report
@@ -458,7 +462,7 @@ are derived from <<IALA>>. Message type 23 was decribed to me by Mike
Greene based on <<IEC-62287>>. Message type 24 was described to me by
<<Schwehr>>, whose Python toolkit decodes it. Message types 25-26 are
reported by <<Schwehr>>, who observes they were added in Version 3 of
-<<ITU1371>>.
+<<ITU1371>>. Message type 27 is direct from <<ITU1371>> 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
@@ -471,7 +475,7 @@ set to use.
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-26. Also, the interpretation of IMO extension subtypes of messages
+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
@@ -559,7 +563,7 @@ 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.
-Position accuracy flag indicates the accuracy of the fix. A value of
+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.
@@ -2167,8 +2171,10 @@ than 9, and (c) end padding changes from 6 to 10 bits.
|38-39 | 2 |Spare | |Not used
|40-55 | 16 |DAC/FID | |DAC = 001 FID = 11
|56-80 | 25 |Longitude |lon |Signed: unit minutes * 0.001
+| | | | |East positive, West negative
| | | | |181000 = N/A (default)
|81-104 | 24 |Latitude |lat |Signed: unit minutes * 0.001
+| | | | |North positive, South negative
| | | | |91000 = N/A (default)
|105-105 | 1 |Fix quality |accuracy |As in Common Navigation Block
|106-110 | 5 |Day |day |1-31, 0=N/A (default)
@@ -2932,7 +2938,7 @@ Takes up 60-1064 bits (up to 5 slots).
[frame="topbot",options="header"]
|==============================================================================
|Field |Len |Description | Member | Units
-|0-5 | 6 | Message Type | type | Unsigned integer: 25
+|0-5 | 6 | Message Type | type | Unsigned integer: 26
|6-7 | 2 | Repeat Indicator | repeat | As in CNB
|8-37 | 30 | MMSI | mmsi | Unsigned integer: 9 digits
|38 | 1 | Destination indicator| addressed | 0=broadcast,1=addressed
@@ -2957,6 +2963,39 @@ whether it should be interpretred as a SOTDMA or ITDMA state.
Note: Type 26 is extremely rare. As of March 2010 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
+
+[frame="topbot",options="header"]
+|==============================================================================
+|Field |Len |Description |Member |Units
+|0-5 | 6 |Message Type |type |Unsigned integer: 27
+|6-7 | 2 |Repeat Indicator |repeat |As in CNB
+|8-37 | 30 |MMSI |mmsi |Unsigned integer: 9 digits
+|38-38 | 1 |Position Accuracy |accuracy |See Common Navigation Block
+|39-39 | 1 |RAIM flag |raim |See Common Navigation Block
+|40-43 | 4 |Navigation Status |status |See Common Navigation Block
+|44-61 | 18 |Longitude |lon |Signed: minutes/10
+| | | | |East positive, West negative
+| | | | |181000 = N/A (default)
+|62-78 | 17 |Latitude |lat |Signed: minutes/10
+| | | | |North positive, South negative
+| | | | |91000 = N/A (default)
+|79-84 | 6 |Speed Over Ground |speed |Knots (0-62); 63 = N/A (default)
+|85-93 | 9 |Course Over Ground |course |0 to 359 degrees,
+| | | | |511 = not available
+|94-94 | 1 |GNSS Position status|gnss |0 = current GNSS position
+| | | | |1 = not GNSS position (default)
+|95-95 | 1 |Spare | |Not used
+|==============================================================================
+
+Note: Type 27 has not been observed in the wild as of early 2011.
+
== Local extensions ==
Some regional authorities extend the AIS message set.
@@ -3177,7 +3216,7 @@ 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, and 21-24.
+scaled dumps will differ are 1-5, 9, 11, 17-19, 21-24, and 27.
5. In unscaled mode, float-valued fields are dumped in their unscaled
integer form. In scaled mode, division or other specified scaling is
@@ -3212,6 +3251,7 @@ integer indices. In scaled mode, the values are dumped as strings.
| 21 | lon, lat | aid_type, epfd
| 22-23 | ne_lon,ne_lat, sw_lon, sw_lat | -
| 24 | - | shiptype
+| 27 | lon, lat | -
|===========================================================================
As the Beaufort scale is usually quoted numerically, conforming implementations
@@ -3387,8 +3427,8 @@ Version 1.27 describes the sometime U.S. practice of omitting the leading
Version 1.28 merges updates from IMO 289, communicated by Kurt Schwehr.
-Version 1.29 added much information on WMO special message format in
+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".
+Also, we describe "pilot plugs" and AIS message type 27.
diff --git a/www/upload b/www/upload
index c3b4e913..4cf8447c 100755
--- a/www/upload
+++ b/www/upload
@@ -9,7 +9,7 @@ webdir=shell.berlios.de:/home/groups/gpsd/htdocs
#cgidir=shell.berlios.de:/home/groups/gpsd/cgi-bin
# Ensure all derived HTML and checksums are up to date.
-(cd ..; make website)
+(cd ..; scons website)
if [ $1 ]