summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2009-03-15 06:38:17 +0000
committerEric S. Raymond <esr@thyrsus.com>2009-03-15 06:38:17 +0000
commit4f627e90862866164d1e0e1c0ac3ca85e8373f56 (patch)
treeb9cf75dba85794f10c627025ed1cbcfa12d6bd2a
parentb3f49700b7f032a4cd0fe5d15ef4b747ad580f9f (diff)
downloadgpsd-4f627e90862866164d1e0e1c0ac3ca85e8373f56.tar.gz
Check in AIVDM regression tests for sentence types 1-4.
-rw-r--r--Makefile.am21
-rw-r--r--bits.c39
-rw-r--r--packet.c4
-rw-r--r--test/schwehr.aivdm125
-rw-r--r--test/schwehr.aivdm.chk118
-rw-r--r--www/AIVDM.txt41
6 files changed, 320 insertions, 28 deletions
diff --git a/Makefile.am b/Makefile.am
index efd89229..4ae29d71 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -438,6 +438,25 @@ rtcm-makeregress: gpsdecode
$(srcdir)/gpsdecode < $${f} > $${f}.chk; \
done
+
+# Regression-test the AIVDM decoder.
+aivdm-regress: gpsdecode
+ @echo "Testing AIVDM decoding..."
+ @mkdir -p test
+ @for f in $(srcdir)/test/*.aivdm; do \
+ echo "Testing $${f}..."; \
+ $(srcdir)/gpsdecode <$${f} >test/test.chk; \
+ diff -ub $${f}.chk test/test.chk; \
+ done; \
+ rm test/test.chk
+
+# Rebuild the AIVDM regression tests.
+aivdm-makeregress: gpsdecode
+ @for f in $(srcdir)/test/*.aivdm; do \
+ $(srcdir)/gpsdecode < $${f} > $${f}.chk; \
+ done
+
+
# Regression-test the packet getter.
packet-regress: test_packet
@echo "Testing detection of invalid packets..."
@@ -471,7 +490,7 @@ time_regress: test_mkgmtime
./test_mkgmtime
# Do all normal regression tests
-testregress: gps-regress rtcm-regress packet-regress undump-regress time_regress
+testregress: gps-regress rtcm-regress aidvm-regress packet-regress undump-regress time_regress
@echo "Regressions complete."
# We would like "${MAKE} check" to run the regression tests. automake
diff --git a/bits.c b/bits.c
index 41599634..bd807348 100644
--- a/bits.c
+++ b/bits.c
@@ -30,25 +30,30 @@ unsigned long long ubits(char buf[], unsigned int start, unsigned int width)
fld <<= BITS_PER_BYTE;
fld |= (unsigned char)buf[i];
}
-#ifdef UDEBUG
- printf("Extracting %d:%d from %s: segment 0x%llx = %lld\n", start, width,
- gpsd_hexdump(buf, 12), fld, fld);
-#endif /* UDEBUG */
+#ifdef DEBUG
+ (void)printf("%d:%d from %s:\n", start, width, gpsd_hexdump(buf, 32));
+#endif
+#ifdef DEBUG
+ (void)printf(" segment=0x%llx,", fld);
+#endif /* DEBUG */
end = (start + width) % BITS_PER_BYTE;
if (end != 0) {
fld >>= (BITS_PER_BYTE - end);
-#ifdef UDEBUG
- printf("After downshifting by %d bits: 0x%llx = %lld\n",
- BITS_PER_BYTE - end, fld, fld);
+#ifdef DEBUG
+ (void)printf(" after downshifting by %d bits: 0x%llx",
+ BITS_PER_BYTE - end, fld);
#endif /* UDEBUG */
}
+#ifdef DEBUG
+ (void)printf(" = %lld\n", fld);
+#endif /* UDEBUG */
fld &= ~(-1LL << width);
-#ifdef UDEBUG
- printf("After selecting out the bottom %u bits: 0x%llx = %lld\n",
- width, fld, fld);
-#endif /* UDEBUG */
+#ifdef DEBUG
+ (void)printf(" after selecting out the bottom %u bits: 0x%llx = %lld\n",
+ width, fld, fld);
+#endif /* DEBUG */
return fld;
}
@@ -58,19 +63,19 @@ signed long long sbits(char buf[], unsigned int start, unsigned int width)
{
unsigned long long fld = ubits(buf, start, width);
-#ifdef DEBUG
+#ifdef SDEBUG
(void)fprintf(stderr, "sbits(%d, %d) extracts %llx\n", start, width, fld);
-#endif /* DEBUG */
+#endif /* SDEBUG */
/*@ +relaxtypes */
if (fld & (1 << (width-1))) {
-#ifdef DEBUG
+#ifdef SDEBUG
(void)fprintf(stderr, "%llx is signed\n", fld);
-#endif /* DEBUG */
+#endif /* SDEBUG */
fld |= (-1LL << (width-1));
}
-#ifdef DEBUG
+#ifdef SDEBUG
(void)fprintf(stderr, "sbits(%d, %d) returns %lld\n", start, width, (signed long long)fld);
-#endif /* DEBUG */
+#endif /* SDEBUG */
return (signed long long)fld;
/*@ -relaxtypes */
}
diff --git a/packet.c b/packet.c
index e5645cb0..3f3641c5 100644
--- a/packet.c
+++ b/packet.c
@@ -968,8 +968,10 @@ void packet_parse(struct gps_packet_t *lexer)
else
#endif /* AIVDM_ENABLE */
packet_accept(lexer, NMEA_PACKET);
- } else
+ } else {
+ gpsd_report(LOG_WARN, "bad checksum in NMEA packet.\n");
lexer->state = GROUND_STATE;
+ }
packet_discard(lexer);
break;
}
diff --git a/test/schwehr.aivdm b/test/schwehr.aivdm
new file mode 100644
index 00000000..1ed0c9a2
--- /dev/null
+++ b/test/schwehr.aivdm
@@ -0,0 +1,125 @@
+# Sample AIVDM data sentences provided from real data by Kurt Schwehr
+#
+# Sample sentences of types 1-4.
+#
+!AIVDM,1,1,,A,15RTgt0PAso;90TKcjM8h6g208CQ,0*4A
+# MessageID: 1
+# RepeatIndicator: 0
+# UserID: 371798000
+# NavigationStatus: 0
+# ROT: -127
+# SOG: 12.3
+# PositionAccuracy: 1
+# longitude: -123.395383333
+# latitude: 48.38163333333
+# COG: 224
+# TrueHeading: 215
+# TimeStamp: 33
+# RegionalReserved: 0
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slotoffset: 4252
+#
+!AIVDM,1,1,,A,16SteH0P00Jt63hHaa6SagvJ087r,0*42
+# MessageID: 1
+# RepeatIndicator: 0
+# UserID: 440348000
+# NavigationStatus: 0
+# ROT: -128
+# SOG: 0
+# PositionAccuracy: 0
+# longitude: -70.7582
+# latitude: 43.08015
+# COG: 93.4
+# TrueHeading: 511
+# TimeStamp: 13
+# RegionalReserved: 0
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# stare_slottimeout: 2
+# state_slotoffset: 506
+#
+# 2 is really uncommon
+#
+!AIVDM,1,1,,B,25Cjtd0Oj;Jp7ilG7=UkKBoB0<06,0*60
+# MessageID: 2
+# RepeatIndicator: 0
+# UserID: 356302000
+# NavigationStatus: 0
+# ROT: 127
+# SOG: 13.9
+# PositionAccuracy: 0
+# longitude: -71.62614333333333333333333333
+# latitude: 40.39235833333333333333333333
+# COG: 87.7
+# TrueHeading: 91
+# TimeStamp: 41
+# RegionalReserved: 0
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slottimeout: 3
+# state_slotoffset: 6
+#
+!AIVDM,1,1,,A,38Id705000rRVJhE7cl9n;160000,0*40
+# MessageID: 3
+# RepeatIndicator: 0
+# UserID: 563808000
+# NavigationStatus: 5
+# ROT: 0
+# SOG: 0
+# PositionAccuracy: 1
+# longitude: -76.32753333333333333333333333
+# latitude: 36.91
+# COG: 252
+# TrueHeading: 352
+# TimeStamp: 35
+# RegionalReserved: 0
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slottimeout: 0
+# state_slotoffset: 0
+#
+!AIVDM,1,1,,A,403OviQuMGCqWrRO9>E6fE700@GO,0*4D
+# MessageID: 4
+# RepeatIndicator: 0
+# UserID: 3669702
+# Time_year: 2007
+# Time_month: 5
+# Time_day: 14
+# Time_hour: 19
+# Time_min: 57
+# Time_sec: 39
+# PositionAccuracy: 1
+# Position_longitude: -76.35236166666666666666666667
+# Position_latitude: 36.88376666666666666666666667
+# fixtype: 7
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slottimeout: 4
+# state_slotoffset: 1503
+#
+!AIVDM,1,1,,A,403OviQuMGCqWrRO9>E6fE700@GO,0*4D
+# MessageID: 4
+# RepeatIndicator: 0
+# UserID: 3669702
+# Time_year: 2007
+# Time_month: 5
+# Time_day: 14
+# Time_hour: 19
+# Time_min: 57
+# Time_sec: 39
+# PositionAccuracy: 1
+# Position_longitude: -76.35236166666666666666666667
+# Position_latitude: 36.88376666666666666666666667
+# fixtype: 7
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slottimeout: 4
+# state_slotoffset: 1503
+#
diff --git a/test/schwehr.aivdm.chk b/test/schwehr.aivdm.chk
new file mode 100644
index 00000000..f3d22f7f
--- /dev/null
+++ b/test/schwehr.aivdm.chk
@@ -0,0 +1,118 @@
+# Sample AIVDM data sentences provided from real data by Kurt Schwehr
+#
+# Sample sentences of types 1-4.
+#
+1,0,371798000,Under way using engine,fastleft,12.3,1,-123.3954,48.3816,2240,215,33,0,0,84e1
+# RepeatIndicator: 0
+# UserID: 371798000
+# NavigationStatus: 0
+# ROT: -127
+# SOG: 12.3
+# PositionAccuracy: 1
+# longitude: -123.395383333
+# latitude: 48.38163333333
+# COG: 224
+# TrueHeading: 215
+# TimeStamp: 33
+# RegionalReserved: 0
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slotoffset: 4252
+#
+1,0,440348000,Under way using engine,nan,0.0,0,-70.7582,43.0802,934,511,13,0,0,81fa
+# RepeatIndicator: 0
+# UserID: 440348000
+# NavigationStatus: 0
+# ROT: -128
+# SOG: 0
+# PositionAccuracy: 0
+# longitude: -70.7582
+# latitude: 43.08015
+# COG: 93.4
+# TrueHeading: 511
+# TimeStamp: 13
+# RegionalReserved: 0
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# stare_slottimeout: 2
+# state_slotoffset: 506
+#
+# 2 is really uncommon
+#
+2,0,356302000,Under way using engine,fastright,13.9,0,-71.6261,40.3924,877,91,41,0,0,c006
+# RepeatIndicator: 0
+# UserID: 356302000
+# NavigationStatus: 0
+# ROT: 127
+# SOG: 13.9
+# PositionAccuracy: 0
+# longitude: -71.62614333333333333333333333
+# latitude: 40.39235833333333333333333333
+# COG: 87.7
+# TrueHeading: 91
+# TimeStamp: 41
+# RegionalReserved: 0
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slottimeout: 3
+# state_slotoffset: 6
+#
+3,1,563808000,Moored,0,0.0,1,-76.3275,36.9100,2520,352,35,0,0,0
+# RepeatIndicator: 0
+# UserID: 563808000
+# NavigationStatus: 5
+# ROT: 0
+# SOG: 0
+# PositionAccuracy: 1
+# longitude: -76.32753333333333333333333333
+# latitude: 36.91
+# COG: 252
+# TrueHeading: 352
+# TimeStamp: 35
+# RegionalReserved: 0
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slottimeout: 0
+# state_slotoffset: 0
+#
+4,0,003669702,2007:05:14T19:57:39Z,1,36.8838,-76.3524,Surveyed,0,82ef
+# RepeatIndicator: 0
+# UserID: 3669702
+# Time_year: 2007
+# Time_month: 5
+# Time_day: 14
+# Time_hour: 19
+# Time_min: 57
+# Time_sec: 39
+# PositionAccuracy: 1
+# Position_longitude: -76.35236166666666666666666667
+# Position_latitude: 36.88376666666666666666666667
+# fixtype: 7
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slottimeout: 4
+# state_slotoffset: 1503
+#
+# RepeatIndicator: 0
+# UserID: 3669702
+# Time_year: 2007
+# Time_month: 5
+# Time_day: 14
+# Time_hour: 19
+# Time_min: 57
+# Time_sec: 39
+# PositionAccuracy: 1
+# Position_longitude: -76.35236166666666666666666667
+# Position_latitude: 36.88376666666666666666666667
+# fixtype: 7
+# Spare: 0
+# RAIM: False
+# state_syncstate: 0
+# state_slottimeout: 4
+# state_slotoffset: 1503
+#
diff --git a/www/AIVDM.txt b/www/AIVDM.txt
index 9f7b891e..76a9c620 100644
--- a/www/AIVDM.txt
+++ b/www/AIVDM.txt
@@ -30,23 +30,29 @@ found at <<AIS>>.
== Standards ==
-The relevant standard is ITU Recommendation M.1371, "Technical
-Characteristics for a Universal Shipborne Automatic. Identification
-System Using Time Division Multiple Access" <<ITU1371>>, issued in 2001. It is
-proprietary, expensive, and surrounded by attack lawyers, which is why
-this document exists. I have not looked at it.
+ITU Recommendation M.1371, "Technical Characteristics for a Universal
+Shipborne Automatic. Identification System Using Time Division
+Multiple Access" <<ITU1371>>, issued in 2001, describes the format of
+AIS binary messages. It is proprietary, expensive, and surrounded by
+attack lawyers, which is why this document exists. I have not looked
+at it.
ITU-R M.1371 is expanded and clarified by "IALA Technical
Clarifications on Recommendation ITU-R M.1371-1" <<IALA>>, which
is freely available.
+I have been unable to determine what technical standard sets the ASCII
+format for AIS messages; most likely it is <<NMEA>>, which I also have
+not looked at because it is proprietary and expensive and surrounded
+by even more rapacious attack lawyers.
+
== Information Sources ==
Together, the the IALA Technical Clarifications at <<IALA>> and the
Coast Guard's AIS pages at <<NAVCEN>> describe AIS message payloads
almost completely. The detail information on payload formats in this
document is derived from these. Together, they explain everything
-except the Repeat Indicator found in some messages
+except the Repeat Indicator found in some messages.
The AIVDM ASCII packet format is described at <<BOSUN>>.
@@ -56,7 +62,7 @@ There's a web form that does sentence decoding at http://rl.se/aivdm.
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, described at <<NMEA>>.
+navigation systems; NMEA 0183 is described at <<NMEA>>.
Here is a typical AIVDM data packet:
@@ -180,7 +186,7 @@ software.
Field Len Description Units
-------------------------------------------------------------------------------
0-5 6 Message Type Unsigned integer: 1-24
-6-7 2 Repeat Indicator Unknown
+6-7 2 Repeat Indicator Unknown; 3 = "Do not repeat".
8-37 30 MMSI Unsigned integer: 9 decimal digits
38-41 4 Navigation Status See table below
42-49 8 Rate of Turn (ROT) Signed integer: see below
@@ -242,7 +248,7 @@ default.
Latitude is given in in 1/10000 min. Values up to plus or minus 90
degrees, North = positive, South = negative. A value of 91 degrees (0x3412140
-hex) indicates latitude is not available (default).
+hex) indicates latitude is not available and is the default.
Seconds in UTC timestamp should be 0-59, except for these special values:
@@ -418,6 +424,20 @@ Code Ship & Cargo Classification
99 Other Type, no additional information
-------------------------------------------------------------
+== 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 <<SEAWAY>>, freely available), and safety
+information using types 12 and 14.
+
+The U.S. Coast Guard has a system called PAWSS (Port and Water Safety
+System) which uses extended AIS formats. <<SEAWAY>> says it's
+intercompatible with the St. Lawrence Seaway system; I have not
+been able to find any message documentation, however.
+
== References ==
[bibliography]
@@ -439,3 +459,6 @@ Identification System]
- [[[BOSUN]]] http://www.bosunsmate.org/ais/[Marine Automatic Identification System (AIS)]
- [[[NMEA]]] http://gpsd.berlios.de/standards/NMEA.txt[NMEA sentences]
+
+- [[[SEAWAY]]] http://www.greatlakes-seaway.com/en/pdf/aisdata.pdf[St. Lawrence
+ Seaway AIS Data Messaging Formats and Specifications]