summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2011-05-29 11:18:07 -0400
committerEric S. Raymond <esr@thyrsus.com>2011-05-29 11:18:07 -0400
commit2e070b48734a9e3795bd8f6eaa0afc99959eefd8 (patch)
tree7701f84cefb7f98b16ef359b4a0cd2c90fda2e08
parentdfd374545d5822d46380bf07463e0dd8040a9e42 (diff)
downloadgpsd-2e070b48734a9e3795bd8f6eaa0afc99959eefd8.tar.gz
In AIS, support for Route Info (addressed). All regression tests pass.
-rw-r--r--ais_json.c4
-rw-r--r--driver_aivdm.c18
-rw-r--r--gps.h18
-rw-r--r--gpsd_json.c72
-rw-r--r--jsongen.py.in21
5 files changed, 129 insertions, 4 deletions
diff --git a/ais_json.c b/ais_json.c
index c20965f6..8eb97e0a 100644
--- a/ais_json.c
+++ b/ais_json.c
@@ -179,6 +179,10 @@ int json_ais_read(const char *buf,
status = json_read_object(buf, json_ais6_fid25, endptr);
imo = true;
}
+ else if (strstr(buf, "\"fid\":28,") != NULL) {
+ status = json_read_object(buf, json_ais6_fid28, endptr);
+ imo = true;
+ }
else if (strstr(buf, "\"fid\":30,") != NULL) {
status = json_read_object(buf, json_ais6_fid30, endptr);
imo = true;
diff --git a/driver_aivdm.c b/driver_aivdm.c
index 30592663..a5bcdc2c 100644
--- a/driver_aivdm.c
+++ b/driver_aivdm.c
@@ -454,6 +454,24 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type6.dac1fid25.ncargos = i;
break;
case 28: /* IMO289 - Route info - addressed */
+ ais->type6.dac1fid28.linkage = UBITS(88, 10);
+ ais->type6.dac1fid28.sender = UBITS(98, 3);
+ /* 5 bits of type e */
+ ais->type6.dac1fid28.month = UBITS(106, 4);
+ ais->type6.dac1fid28.day = UBITS(110, 5);
+ ais->type6.dac1fid28.hour = UBITS(115, 5);
+ ais->type6.dac1fid28.minute = UBITS(120, 6);
+ ais->type6.dac1fid28.duration = UBITS(126, 18);
+ ais->type6.dac1fid28.waycount = UBITS(144, 5);
+#define ARRAY_BASE 149
+#define ELEMENT_SIZE 55
+ for (i = 0; i < ais->type6.dac1fid28.waycount; i++) {
+ int a = ARRAY_BASE + (ELEMENT_SIZE*i);
+ ais->type6.dac1fid28.waypoints[i].lon = SBITS(a+0, 28);
+ ais->type6.dac1fid28.waypoints[i].lat = SBITS(a+28,27);
+ }
+#undef ARRAY_BASE
+#undef ELEMENT_SIZE
break;
case 30: /* IMO289 - Text description - addressed */
ais->type6.dac1fid30.linkage = UBITS(88, 10);
diff --git a/gps.h b/gps.h
index 625c686f..54ad53cc 100644
--- a/gps.h
+++ b/gps.h
@@ -1027,13 +1027,29 @@ struct ais_t
unsigned int subtype; /* Cargo subtype */
} cargos[28];
} dac1fid25;
+ /* IMO289 - Route info (addressed) */
+ struct {
+ unsigned int linkage; /* Message Linkage ID */
+ unsigned int sender; /* Sender Class */
+ unsigned int rtype; /* Route Type */
+ unsigned int month; /* Start month (UTC) */
+ unsigned int day; /* Start day (UTC) */
+ unsigned int hour; /* Start hour (UTC) */
+ unsigned int minute; /* Start minute (UTC) */
+ unsigned int duration; /* Duration */
+ int waycount; /* */
+ struct waypoint_t {
+ signed int lon; /* Longitude */
+ signed int lat; /* Latitude */
+ } waypoints[16];
+ } dac1fid28;
/* IMO289 - Text message (addressed) */
struct {
unsigned int linkage;
#define AIS_DAC1FID30_TEXT_MAX 154 /* 920 bits of six-bit, plus NUL */
char text[AIS_DAC1FID30_TEXT_MAX];
} dac1fid30;
- /* IMO289 - Tidal Window */
+ /* IMO289 & IMO236 - Tidal Window */
struct {
unsigned int type; /* Message Type */
unsigned int repeat; /* Repeat Indicator */
diff --git a/gpsd_json.c b/gpsd_json.c
index 6a960f51..340d3e86 100644
--- a/gpsd_json.c
+++ b/gpsd_json.c
@@ -1482,7 +1482,7 @@ void json_aivdm_dump(const struct ais_t *ais,
#define SHIPTYPE_DISPLAY(n) (((n) < (unsigned int)NITEMS(ship_type_legends)) ? ship_type_legends[n] : "INVALID SHIP TYPE")
- static char *station_type_legends[16] = {
+ static const char *station_type_legends[16] = {
"All types of mobiles",
"Reserved for future use",
"All types of Class B mobile stations",
@@ -1503,7 +1503,7 @@ void json_aivdm_dump(const struct ais_t *ais,
#define STATIONTYPE_DISPLAY(n) (((n) < (unsigned int)NITEMS(ship_type_legends)) ? station_type_legends[n] : "INVALID STATION TYPE")
- static char *navaid_type_legends[] = {
+ static const char *navaid_type_legends[] = {
"Unspecified",
"Reference point",
"RACON",
@@ -1540,7 +1540,7 @@ void json_aivdm_dump(const struct ais_t *ais,
#define NAVAIDTYPE_DISPLAY(n) (((n) < (unsigned int)NITEMS(navaid_type_legends[0])) ? navaid_type_legends[n] : "INVALID NAVAID TYPE")
- static char *signal_legends[] = {
+ static const char *signal_legends[] = {
"N/A",
"Serious emergency – stop or divert according to instructions.",
"Vessels shall not proceed.",
@@ -1560,6 +1560,40 @@ void json_aivdm_dump(const struct ais_t *ais,
#define SIGNAL_DISPLAY(n) (((n) < (unsigned int)NITEMS(signal_legends[0])) ? signal_legends[n] : "INVALID SIGNAL TYPE")
+ static const char *route_type[32] = {
+ "Undefined (default)",
+ "Mandatory",
+ "Recommended",
+ "Alternative",
+ "Recommended route through ice",
+ "Ship route plan",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Reserved for future use.",
+ "Cancel route identified by message linkage",
+ };
(void)snprintf(buf, buflen, "{\"class\":\"AIS\",");
if (device != NULL && device[0] != '\0')
@@ -1884,6 +1918,38 @@ void json_aivdm_dump(const struct ais_t *ais,
(void)strlcat(buf, "]}\r\n,", buflen - strlen(buf));
break;
case 28: /* IMO289 - Route info - addressed */
+ (void)snprintf(buf + strlen(buf), buflen - strlen(buf),
+ "\"linkage\":%u,\"sender\":%u",
+ ais->type6.dac1fid28.linkage,
+ ais->type6.dac1fid28.sender);
+ if (scaled)
+ (void)snprintf(buf + strlen(buf), buflen - strlen(buf),
+ "\"rtype\":\"%s\"",
+ route_type[ais->type6.dac1fid28.rtype]);
+ else
+ (void)snprintf(buf + strlen(buf), buflen - strlen(buf),
+ "\"rtype\":%u",
+ ais->type6.dac1fid28.rtype);
+ (void)snprintf(buf + strlen(buf), buflen - strlen(buf),
+ "\"month\":%u,\"day\":%u,\"hour\":%u,\"minute\":%u,\"duration\":%u,\"waycount\":%u",
+ ais->type6.dac1fid28.month,
+ ais->type6.dac1fid28.day,
+ ais->type6.dac1fid28.hour,
+ ais->type6.dac1fid28.minute,
+ ais->type6.dac1fid28.duration,
+ ais->type6.dac1fid28.waycount);
+ for (i = 0; i < ais->type6.dac1fid28.waycount; i++) {
+ if (scaled)
+ (void)snprintf(buf + strlen(buf), buflen - strlen(buf),
+ "\"lon\":%.4f,\"lat\":%.4f",
+ ais->type6.dac1fid28.waypoints[i].lon / AIS_LATLON4_SCALE,
+ ais->type6.dac1fid28.waypoints[i].lat / AIS_LATLON4_SCALE);
+ else
+ (void)snprintf(buf + strlen(buf), buflen - strlen(buf),
+ "\"lon\":%d,\"lat\":%d",
+ ais->type6.dac1fid28.waypoints[i].lon,
+ ais->type6.dac1fid28.waypoints[i].lat);
+ }
break;
case 30: /* IMO289 - Text description - addressed */
(void)snprintf(buf + strlen(buf), buflen - strlen(buf),
diff --git a/jsongen.py.in b/jsongen.py.in
index 37ce1ad2..f131238c 100644
--- a/jsongen.py.in
+++ b/jsongen.py.in
@@ -205,6 +205,27 @@ ais_specs = (
'stringbuffered' : ('arrival', 'berth_name',),
},
{
+ "initname" : "json_ais6_fid28",
+ "headers": ("AIS_HEADER","AIS_TYPE6",),
+ "structname": "ais->type6.dac1fid28",
+ "fieldmap":(
+ # fieldname type default
+ ('linkage', 'uinteger', '0'),
+ ('sender', 'uinteger', '0'),
+ ('rtype', 'uinteger', '0'),
+ ('month', 'uinteger', 'AIS_MONTH_NOT_AVAILABLE'),
+ ('day', 'uinteger', 'AIS_DAY_NOT_AVAILABLE'),
+ ('hour', 'uinteger', 'AIS_HOUR_NOT_AVAILABLE'),
+ ('minute', 'uinteger', 'AIS_MINUTE_NOT_AVAILABLE'),
+ ('duration', 'uinteger', '0'),
+ ('waypoints', 'array', (
+ ('waypoint_t', 'waycount', (
+ ('lon', 'integer', 'AIS_LON4_NOT_AVAILABLE'),
+ ('lat', 'integer', 'AIS_LAT4_NOT_AVAILABLE'),
+ )))),
+ ),
+ },
+ {
"initname" : "json_ais6_fid30",
"headers": ("AIS_HEADER","AIS_TYPE6",),
"structname": "ais->type6.dac1fid30",